Drag n Drop Button and Drop-down menu PyQt/Qt designer

前端 未结 4 2041
悲&欢浪女
悲&欢浪女 2020-12-11 11:27

I would like to know the \"best practice\" to change the behavior of some buttons to do the following:

I want with a click to appear a menu. Or when you drag this sa

相关标签:
4条回答
  • 2020-12-11 11:49

    In order to add code to a UI generated with QtDesigner, you must generate a .py file using pyuic:

    pyuic myform.ui -o ui_myform.py
    

    This ui_myform.py file, contains generated code that you should not edit, so later you can change your .ui file with QtDesigner, re-run pyuic, and get ui_myform.py updated without loosing any work.

    The generated file will have a class Ui_myForm(object) (named after on your main widget's name), with a def setupUi(self, myForm) method inside. One way this can be used, is by creating your own class MyForm (on a separate file) which will inherit Ui_myForm, and some other Qt Class, like QWidget or QDialog:

    myform.py:

    from ui_myform import Ui_myForm
    from PyQt4.QtGui import QDialog
    
    class MyForm(QDialog, Ui_myForm):
    
        def __init__(self, parent = None):
            QDialog.__init__(self, parent)
    
            self.setupUi(self)    #here Ui_myForm creates all widgets as members 
                                  #of this object.
                                  #now you can access every widget defined in 
                                  #myForm as attributes of self   
    
            #supposing you defined two pushbuttons on your .UI file:
            self.pushButtonB.setEnabled(False)
    
            #you can connect signals of the generated widgets
            self.pushButtonA.clicked.connect(self.pushButtonAClicked)
    
    
    
        def bucar_actualizaciones(self):
            self.pushButtonB.setEnabled(True)
    

    The names of the widgets are the one you set on QtDesigner, but is easy to inspect ui_myform.py in order to see the available widgets and names.

    In order to use a custom widget in QtDesigner, you can right-click the button, and go to Promote to.... There you'l have to enter:

    • Base class name: QPushButton for example
    • Promoted class name: MyPushButton (this must be the name of the class of your custom widget)
    • Header file: mypushbutton.h. This will be converted to .py by pyuic.

    Click Add and then Promote.

    When you run pyuic, it will add this line at the end of ui_myform.py

    from mypushbutton import MyPushButton
    

    Also, you'll see that the generated code used MyPushButton instead of QPushButton

    0 讨论(0)
  • 2020-12-11 11:59

    My feeling is that you could try to achieve this with standard QWidget, but it would be easier to use QGraphicsScene/QGraphicsView API.

    Also, note that you can embed a QWidget in a QGraphicsScene, using QGraphicsProxyWidget.

    0 讨论(0)
  • 2020-12-11 12:00

    If you want to draw a line between the buttons, it means you need to reimplement the "paintEvent" of the background widget (Possibly the parent widget of all subwidgets), as you said, this is NOT the best practice to do so. Instead, you need to use QGraphicsWidget, for drawing line, you need to use QGraphicsLineItem. It have the following member functions:

    setAcceptDrops
    dragEnterEvent ( QGraphicsSceneDragDropEvent * )
    dragLeaveEvent ( QGraphicsSceneDragDropEvent * )
    dragMoveEvent ( QGraphicsSceneDragDropEvent * )
    

    In the PyQt4 installation folder, there should exist a folder naming examples\graphicsview\diagramscene, which you take it for a reference.

    0 讨论(0)
  • 2020-12-11 12:03

    You need to use a QDropEvent, I know this is not a very good answer but just create a QDropEvent function and in that function check the dropped button.

    If firstButton's dropped on secondButton, painter->drawLine(firstButton.pos(), secondButton.pos()); You can use other points for drawing the line. Or you can use event->source() for the dragged button. You might need to define a QPen with some settings. When I say other points to use, I mean like firstButton.boundingRect().topRight().x(), firstButton.boundingRect.bottomRight().y() - firstButton.boundingRect.height() / 2

    See: http://doc.qt.io/qt-5/qdropevent.html

    Sorry, this code is pseudo C++ code, but you can easily adapt it to Python.

    Example:

     void MainWindow::dropEvent(QDropEvent *event)
     {
         if(event->pos() == somePoint) //somePoint should be inside target's boundingRect, you need to write basic collision detection
              painter->drawLine(event->source().pos(), event->pos()); //You might use other points
     }
    

    There are other drag and drop events also. You can change the target's color for example if dragged over it. See http://doc.qt.io/qt-5/dnd.html

    I can try to help with collision detection code if you need it. I don't know if there's better way though. There may be. I'm mostly a C++ coder, but I can provide basic examples.

    And the dropdown menu. You can create a simple QWidget with your menu with some mouseEvents and make it a child of the button, and set the y position of it so it shows under the button. For example (Again, C++, sorry):

     dropDownMenu->setParent(someButton);
     dropDownMenu->setPos(someButton.x(), someButton.y() + someButton.boundingRect().height());
    

    You can hide or show it with mouseReleaseEvent. Just make sure to hide it back in your dropEvent function, so when you drag and drop it, it doesn't show.

    Edit: Let me show you a simple collision detection code in C++, but easily adaptable to Python.

     if(event->pos() > target.boundingRect().topLeft().x() && event->pos() < target.topRight.x() && event->pos() > target.boundingRect().topRight() && event->pos() < target.boundingRect().bottomRight()) {
          //It's on the button.
     }
    

    If you want a simpler solution. Just subclass the buttons you're going to drop onto and add the drag and drop events in their class. This would be easier, and shorter. I think dropEvent should work in a subclass too. I haven't tried it.

    Edit: If you're asking how to do all of them using only Qt Designer, you can't. You need to write some code. You can't develop programs with Qt Designer, it's just for making the ui more easily. You can make software without Qt Designer, but you can't make software with only Qt Designer. You'll need to learn a bit of Python programming and a bit of PyQt for tasks like this. But both Python and Qt are easy enough to get the hang of them in a short time, and Qt documentation is marvellous.

    Good luck!

    0 讨论(0)
提交回复
热议问题