2016-09-30 1 views
2

Я использую Qt 5 и C++, и я хочу, чтобы некоторые из моих дочерних окон имели свои собственные записи в панели задач. Прямо сейчас я могу создать безсловные QWidgets и использовать механизм сигнального слота, чтобы закрыть эти окна, когда основное окно (QMainWindow) закрыто.Qt: Принудительное дочернее окно для ввода собственной панели задач

Однако, поскольку я добавляю все больше и больше родителей и детей, вся эта техника слот-сигнала будет утомительной (не так ли?), И я уверен, что у Qt уже есть функция, которую я могу использовать для этого. Я видел this; Начальная и средняя Windows раздел рассказывает о том, что я пытаюсь сделать. В нем говорится:

Кроме того, QWidget, имеющий родителя, может стать окном на , устанавливая флаг Qt :: Window. В зависимости от системы управления окном такие вторичные окна обычно укладываются поверх их соответствующего родительского окна и не имеют собственной панели задач.

Я вижу, что мне нужно установить мой QWidgets в Primary Windows, но я не знаю точно, как это сделать.

Так что я пробовал:

// when a QMainWindow's (this) push button is clicked: 
QWidget* newWindow = new QWidget(this, Qt::Window); 
newWindow->show(); 

Это не дает мне поведение я хочу. Как я могу установить newWindow в качестве Первичное окно, сохраняя при этом this своим родителем?

ответ

0

Крупной на основе плакатов идеи Майка Константин Т. х и, я разработал два класса, MyWidget и MyMainWindow, которые могут использовать себя и друг друга в своих конструкторах создавать дочерние окна, которые будут иметь свои собственные записи на панели задач в то время как все еще действуя как дети в их родительские окна (т.е. автоматически закрываются и уничтожаются по окончании родительского окна). MyWidget заменяет QWidget и MyMainWindow заменяет QMainWindow, если такое поведение необходимо.

my_widget.h:

#ifndef MY_WIDGET_H 
#define MY_WIDGET_H 

#include <QWidget> 
#include <QMainWindow> 

class MyMainWindow; 

class MyWidget : public QWidget{ 

    Q_OBJECT 

public: 
    MyWidget(MyWidget* parent = 0){ 
     if(parent){ 
      connect(parent, SIGNAL(window_closed()), 
        this, SLOT(close())); 
      connect(parent, SIGNAL(destroyed(QObject*)), 
        this, SLOT(deleteLater())); 
     } 
    } 

    MyWidget(MyMainWindow* parent); 

    void closeEvent(QCloseEvent* event){ 
     emit window_closed(); 
     QWidget::closeEvent(event); 
    } 

signals: 
    void window_closed(); 
}; 

class MyMainWindow : public QMainWindow{ 

    Q_OBJECT 

public: 
    MyMainWindow(MyMainWindow* parent = 0){ 
     if(parent){ 
      connect(parent, SIGNAL(window_closed()), 
        this, SLOT(close())); 
      connect(parent, SIGNAL(destroyed(QObject*)), 
        this, SLOT(deleteLater())); 
     } 
    } 

    MyMainWindow(MyWidget* parent){ 
     connect(parent, SIGNAL(window_closed()), 
       this, SLOT(close())); 
     connect(parent, SIGNAL(destroyed(QObject*)), 
       this, SLOT(deleteLater())); 
    } 

    void closeEvent(QCloseEvent* event){ 
     emit window_closed(); 
     QMainWindow::closeEvent(event); 
    } 

signals: 
    void window_closed(); 
}; 

#endif // MY_WIDGET_H 

my_widget.cpp:

#include "my_widget.h" 

MyWidget::MyWidget(MyMainWindow* parent){ 
    connect(parent, SIGNAL(window_closed()), 
      this, SLOT(close())); 
    connect(parent, SIGNAL(destroyed(QObject*)), 
      this, SLOT(deleteLater())); 
} 

Пример главной.каст:

#include <QApplication> 
#include "my_widget.h" 

int main(int argc, char* argv){ 
    QApplication a(argc, argv); 

    MyWidget mw1{new MyWidget}; 
    mw1.setWindowTitle("ctor: MyWidget(MyWidget*)"); 
    mw1.show(); 

    MyMainWindow mmw1{&mw1}; 
    mmw1.setWindowTitle("ctor: MyMainWindow(MyWidget*)"); 
    mmw1.show(); 

    MyMainWindow mmw2{&mmw1}; 
    mmw2.setWindowTitle("ctor: MyMainWindow(MyMainWindow*)"); 
    mmw2.show(); 

    MyWidget mw2{&mmw2}; 
    mw2.setWindowTitle("ctor: MyWidget(MyMainWindow*)"); 
    mw2.show(); 
    return a.exec(); 
} 

Так окно цепи: mw1 -> mmw1 -> mmw2 -> mw2 где любое окно, которое закрывается также уничтожить все окна справа от нее и все окна в цепочке будут иметь свои собственные записи на панели задач.

Я уверен, что есть более элегантные способы определения конструкторов в my_widget.h, но в качестве новичка это работало для меня, чтобы получить точное поведение, в котором я нуждался. Я был бы рад увидеть лучшие практики на my_widget.h.

1

Я не являюсь теперь родным методом для этого в Qt. Но вы можете использовать для него сигнал/слот, это определенно не создает серьезной нагрузки на процессор, пока у вас не будет хотя бы тысячи окон. Для этого вы можете реализовать свой собственный родительский механизм.

Например:

class myOwnWidget: public QWidget{ 
    Q_OBJECT 
public: 
    myOwnWidget(myOwnWidget* parent = 0): 
     QWidget(){ 
     if(parent){ 
      connect(parent,SIGNAL(close()), this,SLOT(deleteLater())); 
     } 
    } 

    void closeEvent(QCloseEvent* e){ 
     emit close(); 
     QWidget::closeEvent(e); 
    } 

signals: 
    void close(); 
}; 

class PrimaryWindow : public myOwnWidget{ 
    PrimaryWindow(myOwnWidget *parent): 
     myOwnWidget(parent) 
    { 
     //your constructor here 
    } 

}

с помощью:

PrimaryWindow * rootWindows = new PrimaryWindow(); 
PrimaryWindow * childWin = new PrimaryWindow(rootWindows); 

В коде PrimaryWindow создать без Qt-родителя, но и для закрытия дочерних окон, вы должны наследовать все ваши окна от myOwnWidget ,

Надеюсь, что это поможет.

+1

Почему вы подключаетесь к 'deleteLater()' slot, а не 'close()'? возможно, у вас должно быть имя вашего сигнала как 'closed()' вместо этого? – Mike

+0

Я запустил его, но чтобы получить точное поведение, которое я хотел, мне пришлось взять совет @ Майка и сначала переименовать сигнал в нечто иное, чем 'close()' и подключить его к слоту 'close()'. Когда я так устроен, я могу наследовать новые окна из «PrimaryWindow», сохраняя поведение, которое я хочу. Механизм сигнала-слота, описанный здесь, намного более умен, чем тот, который у меня был в моих классах, и он делает то, что я хочу; однако я подожду некоторое время, прежде чем я приму этот ответ, потому что мне очень хотелось бы знать, можно ли это сделать с помощью флажков с окнами. Спасибо вам как – Deniz

+1

@Deniz. Чтобы подражать владельцу 'QObject', вы можете подключить' destroy' от родителя к слоту 'deleteLater'. (что-то вроде 'connect (parent, SIGNAL (destroy()), это, SLOT (deleteLater());') в дополнение к подключению нашего 'closed()' сигнала к 'close()' slot. – Mike