[Solved] Can't move QPushButton in QGraphicsScene?
There is the code:
int main(int argc, char *argv)
QApplication a(argc, argv);
QGraphicsScene scene(QRectF(-100, -100, 300, 300)); QGraphicsView view(&scene); QGraphicsRectItem* rectItem = new QGraphicsRectItem(0, &scene); rectItem->setPen(QPen(Qt::black)); rectItem->setBrush(QBrush(Qt::green)); rectItem->setRect(QRectF(-30, -30, 120, 80)); rectItem->setFlags(QGraphicsItem::ItemIsMovable); QPushButton* button = new QPushButton("Ok"); QGraphicsProxyWidget* widgetItem = scene.addWidget(button); widgetItem->setFlags(QGraphicsItem::ItemIsMovable); view.show(); return a.exec();
The problem is that I can't move QPushButton, for example QGraphicsRectItem have moved good.
What should I do to make QPushButton movable, and if possible without the inheritance just to set some flags or properties?
I think that the problem is, that QPushButton handles the mouse press itself, and thus blocks out the graphics view system to start moving the item.
Sounds right, and don't you know how to make it start moving?
Perhaps the question is: what do you expect would happen? I mean: does clicking initiate a move, or a click on the button?
When I clicking on button and start moving.
I want the same behavior as QGraphicsRectItem have, but don't know how))
And one more, I want that button only draws on scene and moving like simple QGraphicsItem, without hot tracking, hadling of mouse event and so on. What can I do for that?
P.S. Sorry for english.
And more correct, I want to have the button had the same behavior like in Qt Designer.
[Edit: merged three separate messages into one. Please use the Edit button to add to your last message - Andre]
So, if I understand you correctly, you don't want your button to function like a button at all. It should just look like one. Do I get that right?
In that case, I would simply disgard using QGraphicsProxyWidget completely (it is not a recommended item to use anyway, as it has issues the Trolls have not been able to sort out). Instead, you can create your own QGraphicsRectItem decendant, and reimplement the paint operation. In that operation, you get the current style, and use QStyle::drawControl to draw a button. This will give you a graphics item that looks exactly like any button on your system, but that you can manipulate in the same way as any other graphics item. Of course, it won't have the event handling, signals and slots that QPushButton offers, but you just said you don't need those anyway.
Andre, thanks a lot, this is exactly what I want.
And again thanks
Could you show how would be implemented "paint" method?
I tried but had no success
If you show us what you tried, we may be able to help you fix the issue.
I'm doing in pyqt
def init(self, itemUI, scene=None, parent=None):
super(ItemUI, self).init(parent, scene)
self.item = itemUI
self.setRect(QRectF(10, 10, 100, 50))
def paint(self, painter, option, widget=None):
self.item.style().drawControl(QStyle.CE_PushButton, option, painter, widget)@
- itemUI is the UI Item, for example a QPushButton
- Nothing shows on the screen
I still find Python hard to read, so I might be off here:
I think you will need to construct your own option struct, and fill it with the proper values for the button that you want to draw. You can not just pass a QStyleOptionGraphicsItem if you want to draw a button and expect it to work.
I have no idea of how to create a option struct but I'll try here...
any doubt I will return here
Thank you for your assistance and availability.
and sorry for my poor english =]
try this creation and further adapt to your implementation
void GraphicsRectItemButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget widget)
QStyle style = qApp->style();
buttonOption.rect = option->rect;
buttonOption.state = option->state;
buttonOption.text = "ItemButton";
style->drawControl(QStyle::CE_PushButton, &buttonOption, painter, widget);
I think I understand what you are trying to do: pass a QPushButton to your ItemUI instance, then ask the button to paint itself, as the implementation of your ItemUI.paint().
I believe Andre is saying that the paint method of a QGraphicsRectItem is passed an option of type QStyleOptionGraphicsItem but QStyle.drawControl expects an option of type QStyleOptionButton. Both types are subclasses of QStyleOption, but they may have different attributes.
Also, who knows the default attributes of a QPushButton's style? One would hope it defaults to something sensible and visible.
Also, if the QPushButton instance is not realized (shown), possibly it's paint method (style.drawControl()) returns a None path (just calls Python pass)?
Possibly you should do the painting yourself, instead of asking the button widget to paint itself. You could access the style of the button for attributes needed to paint. But I agree with your design, if you use the button's paint implementation, it would be foolproof against changes to Qt toolkit. You would get a style that matches the style of other buttons in the GUI. Your ItemUI would be a graphics item, not a widget, but would look like a button widget.
I would be interested in any solution you came up with.
What you could do, is look into the way the Quick components for desktop are implemented. As you may or may not be aware of, in Quick 1.x, items there are QGraphicsItems. The desktop components render these items using the Qt style API. I think that could be a good source of inspiration. The full source code is online for it.
Thanks, thats a good idea.
I think you are saying that you don't need to create a dependency on QWidget (shouldn't, since the QGui module is deprecated on some platforms?) Instead the Qt style API has all you need to insure that the style of your custom GUI items (whatever you call them: widgets, controls, etc.) conform to the platform's guidelines and the user's preferences. Don't arbitrarily fabricate a style attribute if it can come from the Qt style API.
This is pertinent to my case because I am implementing a custom control that in a QGraphicsView. It is a tracking button. It appears on hover. It can be clicked. It follows the mouse (to a certain extent.) It is part of a tracking menu (a tracking menu is a set of tracking buttons.) I am studying whether it needs to be a QWidget (so that it receives mouseMoveEvent easily) or a QGraphicsItem. This is different from what Rokemoon wants (his tracks, ie follows the mouse, when clicked, mine tracks before clicked.) The handling of mouseMoveEvent seems to be easier if it is a QWidget, but as you suggest, it could be a QGraphicsItem as in Qt Quick. I need to study Qt Quick and the design reasons their controls are QGraphicsItems. It is very interesting the differences between event dispatch in QWidget trees and QGraphicItem trees.