2016-10-02 1 views
0

Wenn ich in Windows ein QMainWindow erstelle, kann ich es durch den Bildschirm bewegen, indem ich auf die Titelleiste klicke und es ziehe.Verschieben eines Fensters durch Klicken auf ein internes Widget anstelle der Titelleiste

In meiner Anwendung habe ich die Titelleiste mit setWindowFlags(Qt::CustomizeWindowHint) ausgeblendet und ich versuche, eine benutzerdefinierte Titelleiste mit einem Widget zu erstellen und im Menübereich mit setMenuWidget(myWidget) festlegen.

Jetzt möchte ich das ursprüngliche Verhalten reproduzieren: Ich möchte auf meine MyWidget Widget im QMainWindow klicken und, während die Maus gedrückt wird, zieht die Maus das Fenster.

Gibt es eine Möglichkeit, es zu tun?

Antwort

1

Sie müssen nur das notwendige Mausereignis durch MyWidget Überschreiben ‚s mousePressEvent(), mouseMoveEvent() und mouseReleaseEvent() Handler Handling implementieren.

  1. die Maus erkennt unten, aktuelle Mausposition
  2. Während du zu bewegen, aktuelle Mausposition erhalten, berechnet Unterschied, neue Position zu speichern, Fenster zu verschieben, indem

diff Sie können das Fenster bekommen (top Level-Widget) von innen MyWidget durch die window() Methode.

1

Dies ist ein Beispiel zur Implementierung einer gefälschten Titelleiste, die Standardschaltflächen (Minimieren, Maximieren, Schließen) enthält und zum Verschieben des gesamten Fensters gezogen werden kann (dies basiert auf dem Ansatz in @ Kevins Antwort) .

screenshot

#include <QtWidgets> 


class FakeTitleBar : public QWidget{ 
    Q_OBJECT 
public: 
    explicit FakeTitleBar(QWidget* parent= nullptr):QWidget(parent){ 
     label.setSizePolicy(QSizePolicy::Expanding, 
          QSizePolicy::Expanding); 
     layout.addWidget(&label); 
     layout.addWidget(&buttonMinimize); 
     layout.addWidget(&buttonMaximize); 
     layout.addWidget(&buttonClose); 
     //connecting buttons' signals to slots 
     connect(&buttonMinimize, &QPushButton::clicked, 
       this, &FakeTitleBar::MinimizeWindow); 
     connect(&buttonMaximize, &QPushButton::clicked, 
       this, &FakeTitleBar::MaximizeWindow); 
     connect(&buttonClose, &QPushButton::clicked, 
       this, &FakeTitleBar::CloseWindow); 
     //setting vertical fixed size policy 
     //so that the title bar does not take up any additional space 
     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); 
     //a bit of styling 
     setStyleSheet("QPushButton {margin:0px; padding:5px;}" 
         "QWidget {background-color:blue; color:white;}"); 
    } 

public slots: 
    //slots for corresponding buttons 
    void MinimizeWindow(){ 
     window()->showMinimized(); 
    } 
    void MaximizeWindow(){ 
     if(!window()->isMaximized()) 
      window()->showMaximized(); 
     else 
      window()->showNormal(); 
    } 
    void CloseWindow(){ 
     window()->close(); 
    } 

protected: 
    void mousePressEvent(QMouseEvent* event){ 
     //save the press position (this is relative to the current widget) 
     pressPos= event->pos(); 
     isMoving= true; 
    } 
    void mouseMoveEvent(QMouseEvent* event){ 
     //isMoving flag makes sure that the drag and drop event originated 
     //from within the titlebar, because otherwise the window shouldn't be moved 
     if(isMoving){ 
      //calculate difference between the press position and the new Mouse position 
      //(this is relative to the current widget) 
      QPoint diff= event->pos() - pressPos; 
      //move the window by diff 
      window()->move(window()->pos()+diff); 
     } 
    } 
    void mouseReleaseEvent(QMouseEvent* /*event*/){ 
     //drag and drop operation end 
     isMoving= false; 
    } 
    //double-clicking on the title bar should maximize the window 
    void mouseDoubleClickEvent(QMouseEvent* /*event*/){ 
     MaximizeWindow(); 
    } 
    //in order for the style sheet to apply on this custom widget 
    //see https://doc.qt.io/qt-5/stylesheet-reference.html#qwidget-widget 
    void paintEvent(QPaintEvent *) 
    { 
     QStyleOption opt; 
     opt.init(this); 
     QPainter p(this); 
     style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); 
    } 

private: 
    QHBoxLayout layout{this}; 
    QLabel label{"Fake Title Bar"}; 
    QPushButton buttonMinimize{"-"}; 
    QPushButton buttonMaximize{"M"}; 
    QPushButton buttonClose{"X"}; 
    QPoint pressPos; 
    bool isMoving{false}; 
}; 

//sample usage 

class Widget : public QWidget{ 
public: 
    explicit Widget(QWidget* parent= nullptr):QWidget(parent){ 
     setWindowFlags(Qt::CustomizeWindowHint); 
     layout.addWidget(&titleBar); 
     layout.addWidget(&label); 
     layout.setContentsMargins(0, 0, 0, 0); 
     label.setAlignment(Qt::AlignCenter); 
     //default size for the window 
     resize(320,240); 
    } 
    ~Widget(){} 

private: 
    QVBoxLayout layout{this}; 
    FakeTitleBar titleBar; 
    QLabel label{"this is a sample window"}; 
}; 

int main(int argc, char* argv[]) { 
    QApplication app(argc, argv); 

    Widget w; 
    w.show(); 

    return app.exec(); 
} 

#include "main.moc" 
Verwandte Themen