QFileDialog在新窗口中打开,同时将其添加到QHBoxLayout

时间:2017-08-21 20:20:25

标签: python pyqt pyqt5 qdialog

我的问题是,当我将QFileDialog添加到QVBoxLayout时,它会在新窗口中打开。下面是产生我问题的代码。

from PyQt5.QtWidgets import QVBoxLayout, QFileDialog, QPushButton, QWidget


class MainWindow(QtWidgets.QWidget):
    def __init__(self):
       super(MainWindow, self).__init__()
       self.setWindowTitle("My own MainWindow")

       self.fileDialog = QFileDialog()

       self.confirmAction = QPushButton("Press me", self)

       mainLayout = QVBoxLayout()

       mainLayout.addWidget(self.fileDialog)
       mainLayout.addWidget(self.confirmAction)
       self.setLayout(mainLayout)

2 个答案:

答案 0 :(得分:1)

根据docs

  

窗口标志是一种类型(例如Qt :: Dialog)和零或的组合   更多关于窗口系统的提示(例如Qt :: FramelessWindowHint)。

     

如果小部件有类型Qt :: Widget或Qt :: SubWindow并且变成了   窗口(Qt :: Window,Qt :: Dialog等),它放在位置(0,0)上   桌面。如果小部件是一个窗口并成为Qt :: Widget或   Qt :: SubWindow,它相对于其父项放在位置(0,0)   窗口小部件。

因此,这些标志用于改变窗口小部件的行为,例如将其转换为窗口,对话框,工具提示等。

docs中列出了以下列表:

  

Qt :: Widget :这是默认设置   为QWidget键入。这种类型的小部件是子小部件,如果有的话   父母和独立窗口,如果他们没有父母。也可以看看   Qt :: Window和Qt :: SubWindow。

     

Qt :: Window :表示   小部件是一个窗口,通常带有窗口系统框架和标题   条形图,无论小部件是否具有父级。注意   如果小部件没有,则无法取消设置此标志   家长。

     

Qt :: Dialog :窗口表示窗口小部件是a   应该作为对话框装饰的窗口(即通常没有   最大化或最小化标题栏中的按钮)。这是默认值   输入QDialog。如果你想将它用作模态对话框,它应该   从另一个窗口启动,或者有一个父母并与之一起使用   QWidget :: windowModality属性。如果你使模态,对话框   将阻止应用程序中的其他顶级窗口获取   任何输入。我们引用一个父级为a的顶级窗口   辅助窗口。

     

Qt :: Sheet :窗口表示   窗口是Macintosh工作表。由于使用工作表意味着窗口   modality,推荐的方法是使用QWidget :: setWindowModality(),   或者QDialog :: open()。

     

Qt ::抽屉:窗口指示   小部件是Macintosh抽屉。

     

Qt :: Popup :窗口表示窗口小部件是弹出的顶级窗口,即   它是模态的,但有一个适合弹出窗口的窗口系统框架   菜单。

     

Qt :: Tool :窗口表示窗口小部件是a   工具窗口。工具窗口通常是小窗口,小于   通常的标题栏和装饰,通常用于工具集合   纽扣。如果有父项,则工具窗口将始终保持打开状态   顶部。如果没有父母,您可以考虑使用   Qt :: WindowStaysOnTopHint也是如此。如果窗口系统支持它,a   工具窗口可以用更轻的框架装饰。它可以   也可以与Qt :: FramelessWindowHint结合使用。

     

在Mac OS X上,工具窗口对应于Floating类的窗口。   这意味着窗口生活在正常窗口之上;它   不可能在它上面放一个普通的窗口。默认情况下,工具   当应用程序处于非活动状态时,窗口将消失。这可以   由Qt :: WA_MacAlwaysShowToolWindow属性控制。

     

Qt :: ToolTip :窗口表示窗口小部件是a   提示。这在内部用于实现工具提示。

     

Qt :: SplashScreen :窗口表示窗口是a   闪屏。这是QSplashScreen的默认类型。

     

Qt :: Desktop :窗口表示此小部件是   桌面。这是QDesktopWidget的类型。

     

Qt :: SubWindow :表示此小部件是子窗口,   例如QMdiSubWindow小部件。

在您的情况下,我们必须将Qt::Dialog的行为更改为Qt::Widget,在以下代码中我会显示执行此操作的代码:

class MainWindow(QWidget):
    def __init__(self):
       super(MainWindow, self).__init__()
       self.setWindowTitle("My own MainWindow")

       self.fileDialog = QFileDialog(self)
       self.fileDialog.setOption(QFileDialog.DontUseNativeDialog)
       self.fileDialog.setWindowFlags(Qt.Widget)

       self.confirmAction = QPushButton("Press me", self)

       mainLayout = QVBoxLayout()

       mainLayout.addWidget(self.fileDialog)
       mainLayout.addWidget(self.confirmAction)
       self.setLayout(mainLayout)

截图:

enter image description here

答案 1 :(得分:0)

我一直在自己调查这个问题,对“只使用非本地对话框”位不满意。我一直在KDE平台文件对话框的实现中四处乱搞,已经(卡在)非常接近我想要的东西上。

我发现的唯一连接点是在实际显示对话框之前;在此之前,似乎没有办法知道实际的父窗口小部件。但是我们可以:

  • 从父级 QWindow 查找父级QWidget
  • 从中获取(第一个)(用户端)QFileDialog实例
  • 如果父QWidget具有布局,则用我们自己的对话框替换找到的QFileDialog实例
  • 保存原始的用户端QFileDialog实例
  • 在dtor中,要么恢复布局中的原始QFD,要么在其上调用deleteLater()(并在操作导致递归调用dtor的情况下将其设置为NULL)。

毛刺: -对话框可能会以2组OK / Cancel / etc结尾。纽扣 -如果没有,这些按钮实际上可能仅关闭嵌入式QFD,而不关闭封闭的对话框(如上面链接的python示例所示) -调整大小有效,但saveSize / restoreSize机制不起作用 -AFAICT所有信号均未正确连接(Scribus打开文件对话框中的预览未对应有的选择做出反应)。文件打开确实可以。

此BKO机票的完整补丁: https://bugs.kde.org/show_bug.cgi?id=404833#c15

很明显,这仅对黑客和可以发布自己的平台主题插件(这是KDE平台文件对话框的来源)的软件有用。幸运的是,这些插件往往相对较小。