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

问题描述 投票:2回答:2

我的问题是,当我将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)
python pyqt pyqt5 qdialog
2个回答
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:Window表示窗口小部件是一个应该被装饰为对话框的窗口(即,标题栏中通常没有最大化或最小化按钮)。这是QDialog的默认类型。如果要将其用作模式对话框,则应从另一个窗口启动它,或者使用父窗口并与QWidget :: windowModality属性一起使用。如果将其设置为模态,则对话框将阻止应用程序中的其他顶级窗口获取任何输入。我们引用一个顶级窗口,它将父级作为辅助窗口。

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

Qt :: Drawer:Window表示小部件是Macintosh抽屉。

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

Qt :: Tool:Window表示窗口小部件是工具窗口。工具窗口通常是一个小窗口,其标题栏和装饰比通常小,通常用于工具按钮的集合。如果有父项,则工具窗口将始终保持在其上。如果没有父级,您可以考虑使用Qt :: WindowStaysOnTopHint。如果窗户系统支持它,工具窗口可以用更轻的框架装饰。它也可以与Qt :: FramelessWindowHint结合使用。

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

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

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

Qt :: Desktop:Window表示此小部件是桌面。这是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


0
投票

我自己一直在研究这个问题,不满意“只使用非原生对话”这一点。我一直在讨论KDE平台文件对话框实现,并且已经(卡住)非常接近我想要的东西。

我发现的唯一附着点就在实际显示对话框之前;在此之前,似乎无法知道实际的父窗口小部件。但我们可以:

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

毛刺: - 对话框最终可能会有2组OK / Cancel /等。按钮 - 如果没有,这些按钮实际上可能只关闭嵌入的QFD而不是封闭对话框(见上面链接的python示例) - 调整大小工作,但saveSize / restoreSize机制没有--AFAICT所有信号都没有正确连接( Scribus打开文件对话框中的预览不会对选择文件做出反应。文件打开确实有效。

这张BKO门票上有完整补丁:https://bugs.kde.org/show_bug.cgi?id=404833#c15

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

© www.soinside.com 2019 - 2024. All rights reserved.