我有一个扩展的主窗口,其中添加了QtGui.QTabWidget
。我正在创建从QtGui.QWidget
扩展的几个小部件,我可以添加和删除这些小部件到选项卡小部件。
我想要做的是有一个“弹出”按钮,可以将子窗口小部件从选项卡窗口小部件中移除,然后显示为它自己的独立窗口(以及一个“弹出式”按钮来放置它回到主窗口)。与Gtalk-in-Gmail相同的想法。 请注意,如果我关闭主窗口,其他“选项卡”或“窗口”也应该关闭,我应该能够并排放置所有窗口并让它们全部可见并同时更新。 (我将显示近实时数据)。
我是Qt的新手,但是如果我没弄错的话,如果Widget没有父母,那么它就会独立出现。这有效,但我不知道如何能够“弹出”窗口。
class TCWindow(QtGui.QMainWindow):
.
.
.
def popOutWidget(self, child):
i = self.tabHolder.indexOf(child)
if not i == -1:
self.tabCloseRequested(i)
self.widgets[i].setParent(None)
self.widgets[i].show()
我的直觉说,两者之间应该仍然存在父/子关系。
有没有办法保留父母但仍然独立出现窗口,或者我误解了Qt的风格?
否则,在子节点中创建一个变量来保存到主窗口的链接(如self.parentalUnit = self.parent()
)是一个好主意还是一个hackish / kludgy的想法?
答案 0 :(得分:10)
保持parent
原样。如果删除parent
,则关闭主窗口将不会关闭“浮动”标签,因为它们现在是顶级窗口。 windowFlags
定义窗口小部件是窗口还是子窗口小部件。基本上,您需要在QtCore.Qt.Window
和QtCore.Qt.Widget
以下是一个小而完整的例子:
#!/usr/bin/env python
# -.- coding: utf-8 -.-
import sys
from PySide import QtGui, QtCore
class Tab(QtGui.QWidget):
popOut = QtCore.Signal(QtGui.QWidget)
popIn = QtCore.Signal(QtGui.QWidget)
def __init__(self, parent=None):
super(Tab, self).__init__(parent)
popOutButton = QtGui.QPushButton('Pop Out')
popOutButton.clicked.connect(lambda: self.popOut.emit(self))
popInButton = QtGui.QPushButton('Pop In')
popInButton.clicked.connect(lambda: self.popIn.emit(self))
layout = QtGui.QHBoxLayout(self)
layout.addWidget(popOutButton)
layout.addWidget(popInButton)
class Window(QtGui.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__()
self.button = QtGui.QPushButton('Add Tab')
self.button.clicked.connect(self.createTab)
self._count = 0
self.tab = QtGui.QTabWidget()
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button)
layout.addWidget(self.tab)
def createTab(self):
tab = Tab()
tab.setWindowTitle('%d' % self._count)
tab.popIn.connect(self.addTab)
tab.popOut.connect(self.removeTab)
self.tab.addTab(tab, '%d' % self._count)
self._count += 1
def addTab(self, widget):
if self.tab.indexOf(widget) == -1:
widget.setWindowFlags(QtCore.Qt.Widget)
self.tab.addTab(widget, widget.windowTitle())
def removeTab(self, widget):
index = self.tab.indexOf(widget)
if index != -1:
self.tab.removeTab(index)
widget.setWindowFlags(QtCore.Qt.Window)
widget.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())
答案 1 :(得分:0)
在Qt中,布局取决于添加到布局的小部件,因此让它处理父级。
您可以创建另一个小部件(没有父级),这个小部件将被隐藏,直到您按下弹出按钮,按下该按钮时,您将从其原始布局中删除“弹出窗口小部件”并将其添加到隐藏窗口小部件的布局中。当按下弹出按钮时 - 将小部件返回到它的原始布局。
要关闭这个隐藏的窗口,当关闭主窗口时,你需要将closeEvent(QCloseEvent* ev)
重新定义为这样的东西(抱歉c ++,但我敢打赌,在python中它都是一样的):
void MainWindow::closeEvent(QCloseEvent* ev)
{
dw->setVisible(false); // independent of mainwindow widget
sw->setVisible(false); // independent of mainwindow widget
QWidget::closeEvent(ev); //invoking close event after all the other windows are hidden
}