How to add QLabel to QGraphicsItem - c++

I have a QGraphicsItem that has text on it. I want this text to be editable, so that if the user double-clicks it, it will enter an edit mode. It seems like the easiest way to do this would be to change the text into a QLineEdit and let the user click away the focus or press enter when they're done.
How can I add a QLineEdit to a QGraphicsItem? I have subclassed the QGraphicsItem so I have access to its internals.

To add any QWidget based object to a QGraphicsScene, a QGraphicsProxyWidget is required.
When you call the function addWidget on QGraphicsScene, it embeds the widget in a QGraphicsProxyWidget and returns that QGraphicsProxyWidget back to the caller.
The QGraphicsProxyWidget forwards events to its widget and handles conversion between the different coordinate systems.
Now that you're looking at using a QLineEdit in the QGraphicsScene, you need to decide if you want to add it directly:
QGraphicsScene* pScene = new QGraphicsScene;
QLineEdit* pLineEdit = new QLineEdit("Some Text");
// add the widget - internally, the QGraphicsProxyWidget is created and returned
QGraphicsProxyWidget* pProxyWidget = pScene->AddWidget(pLineEdit);
Or just add it to your current QGraphicsItem.
Here, you can either add it as a child of the QGraphicsItem:
MyQGraphicsItem* pMyItem = new MyQGraphicsItem;
QGraphicsProxyWidget* pMyProxy = new QGraphicsProxyWidget(pMyItem); // the proxy's parent is pMyItem
pMyProxy->setWidget(pLineEdit); // adding the QWidget based object to the proxy
Or you could add the QGraphicsProxyWidget as a member of your class and call its relevant functions, but adding it as a child is probably much simpler.

QGraphicsTextItem::setTextInteractionFlags (Qt::TextInteractionFlags flags)
API can be used. But you need to create QGraphicsTextItem inside it.
Please check following link for details: Implementation details

You need to create a proxy widget by extending QGraphicsProxyWidget in the case you need some specific behavior or just use a QGraphicsProxyWidget. Take a look at the "Embedded Dialogs" example in your Qt SDK and the QGraphicsProxyWidget documentation. It has been there for a long time so it should be for your version. I hope this helps.

Related

How do I set the parent of a widget after the widget has already been initlized (ex. if the widget is a parameter to a function call)?

I know that usually parents are set by being given in the constructor argument, for example if you wanted to have a push button within a frame you could do:
QFrame frame = new QFrame();
QPushButton* button = new QPushButton(frame);
But I already have the push button that I want to add as a child to a frame (it was received as an argument in the call to the function I'm working on).
Is there any way to add an already existing widget as a child to another widget? Or add a new child to an existing or nonexistent parent?
(Disclaimer: Answer blatantly stolen from G.M.'s comment (with permission - see above ;))
Simply use QWidget's setParent(QWidget *parent) method.
Note: The new parent takes ownership of the QWidget (i.e. deallocating it when the parent is destroyed etc.) and you will need to call show() on the widget again to make it visible, as changing parents turns QWidgets invisible.

Custom class in qt creator

I'm new to Qt and fairly new to C++ but I need help with this issue.
I have a custom class called HybridStack and I want it to extend a QStackedWidget and a QMainWindow.
I want it to extend a QStackedWidget so that I can use as many pages as I need and I want it to extend a QMainWindow so that I could be able to make each page have it's own MenuBar with different content of menu for different page.
I want to add this custom class HybridStack to Qt Designer by
promoting it from a QStackedWidget.
Is this possible? If it is, can you brief me on how to do this? If it's not possible then what's an alternative? Most importantly, I need to use it in the Designer because I need to use qmake
You can't derive from both QStackedWidget and QMainWindow, because both of those are in turn derived from QWidget. If you did so, you'd end up with the Dreaded Diamond. You'll have to use composition instead.
Even then, I'm not sure if it would work correctly to put a QMainWindow within a QStackedWidget, since it is designed to be a top-level item (i.e. its shown directly as a window, not embedded within another QWidget). Another way of accomplishing what you want (menu bar changing when the you change tabs) would be the following:
Make your top-level item a QMainWindow
Make the central widget a custom widget derived from QStackedWidget
When the item showing in the stack widget changes, you can call QMainWindow::setMenuBar to change the menu bar. Each widget within the QStackWidget could have its own QMenuBar instance that it uses for this purpose.

Unable to display Widget when passing this as the parent when initiating

Hi Im learning QT and I have come across something I don't understand. why is it when I create a widget like so
widget = new Widget(this);
widget->show();doesn't display the widget, but if I leave the 'this' out i.e
widget = new widget();
It does display? whats more I need to be able to call one of the parent's methods from the child and unless I set the patient of the child by passing this upon its creation I am unable to do this.
The widget does show up. But it shows up as part of the main window, not in its own window. Of course if the widget you're creating doesn't have any content in it, then you won't see much. You can test this with something like:
widget = new QTextEdit(this);
widget->show();
If you want to make the widget always show up in its own window, then you should have your widget inherit from QDialog instead of from QWidget. Or, if you don't want (or can't) do this, then you should set the Qt::Window window flag when creating the widget:
widget = new Widget(this, Qt::Window);

Combine multiple widgets into one in Qt

I'm repeatedly using a pair of QComboBox and QListWidget in a project. Their interaction is highly coupled - when an item is selected in the combo box, the list is filtered in some way. I'm copy pasting all the signal and slot connections between these two widgets across multiple dialog box implementation which I don't think is a good idea.
Is it possible to create a custom widget, which will hold these two widgets and will have all signal and slot connection in one place? Something like as follows:
class CustomWidget
{
QComboBox combo;
QListWidget list;
...
};
I want to use this widget as a single widget.
The usual way of doing this is to sub-class QWidget (or QFrame).
class CustomWidget: public QWidget {
Q_OBJECT
CustomWidget(QWidget *parent)
: QWidget(parent) {
combo = new QComboBox(...);
list = new QListWidget(...);
// create the appropriate layout
// add the widgets to it
setLayout(layout);
}
private:
QComboBox *combo;
QListWidget *list;
};
Handle all the interactions between the list and the combo in that custom widget (by connecting the appropriate signals to the appropriate slots, possibly defining your own slots for this).
You then expose your custom widget's behavior/API through dedicated signals and slots, possibly mimicking the ones in the list and/or the combo.
The Address book tutorial walks you through all of that, including creating a custom widget and defining signals and slots for it.

Problem with event handling on QToolButton in Linux

I am developing an application, I have added a QToolBar object in that, and have added the QToolButton object on that, I have also connect the clicked() event with that but the problem is that the mouse click event don't work on QToolButton but when I bring focus on that using Tab, then space button works fine, but I want it with mouse click.. any idea? here is the code.
pToolBar = new QToolBar(this);
pToolBar->setAllowedAreas(Qt::NoToolBarArea);//NoToolBarAreaAllToolBarAreas
pToolBar->setFloatable(false);
pToolBar->setGeometry(300,0,160,30);
QToolButton *playButton=new QToolButton(pToolBar);
playButton->setIcon(QIcon("/images/play.png"));
playButton->setGeometry(10,0,40,30);
playButton->setToolTip("Play/Pause");
connect(playButton, SIGNAL(clicked()),SLOT(playButtonClicked()));
The Tool buttons are normally created when new QAction instances are created with QToolBar::addAction() or existing actions are added to a toolbar with QToolBar::addAction().
Example:
QAction *newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
newAct->setShortcut(tr("Ctrl+N"));
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
fileToolBar = addToolBar(tr("File"));
fileToolBar->addAction(newAct);
You can use triggered signal, This signal is emitted when the given action is triggered.
Your example:
QToolButton *playButton=new QToolButton(pToolBar);
connect(playButton, SIGNAL(triggered()),SLOT(playButtonClicked()));
Try explicitly adding the toolbutton to the toolbar. The following code works perfectly for me:
QToolBar *pToolBar = new QToolBar(this);
QToolButton *playButton=new QToolButton(pToolBar);
playButton->setIcon(QIcon("/images/play.png"));
playButton->setText("Play");
playButton->setToolTip("Play/Pause");
playButton->setGeometry(10,0,40,30);
QAction *a = pToolBar->addWidget(playButton);
a->setVisible(true);
connect(playButton, SIGNAL(clicked()),SLOT(playButtonClicked()));
You should probably save the QAction pointer somewhere, since it's the easiest way to assign keyboard shortcuts, enable / disable the button etc. Let me know if this works for you. If it doesn't, perhaps posting a complete compilable example here will help us help you. You should be able to get a small demo program that shows your problem within one or two files.
Cheers,
As jordenysp indirectly explains, the API is QAction centric