Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从连接到QML的PyQt5打开文件对话框_Python_Pyqt_Pyqt5_Qml - Fatal编程技术网

Python 从连接到QML的PyQt5打开文件对话框

Python 从连接到QML的PyQt5打开文件对话框,python,pyqt,pyqt5,qml,Python,Pyqt,Pyqt5,Qml,我在QML中的应用程序窗口中定义了一个按钮(实际上它是一个鼠标earea)。我设法从PyQt5连接到它的clicked事件。现在我试图显示“保存文件”对话框,但出现错误: QWidget: Cannot create a QWidget without QApplication 我的代码如下所示: 从PyQt5.QtCore导入QUrl,QObject#pylint:disable msg=E0611 从PyQt5.QtGui导入qgui应用程序,QIcon#pylint:disable ms

我在QML中的
应用程序窗口中定义了一个按钮(实际上它是一个
鼠标earea
)。我设法从PyQt5连接到它的clicked事件。现在我试图显示“保存文件”对话框,但出现错误:

QWidget: Cannot create a QWidget without QApplication
我的代码如下所示:

从PyQt5.QtCore导入QUrl,QObject#pylint:disable msg=E0611
从PyQt5.QtGui导入qgui应用程序,QIcon#pylint:disable msg=E0611
从PyQt5.QtQml导入QQmlApplicationEngine#pylint:disable msg=E0611
从PyQt5.QtWidgets导入QFileDialog#pylint:disable msg=E0611
def openFile():
options=QFileDialog.options()
选项|=QFileDialog.DontUsenactiveDialog
filename=QFileDialog.getOpenFileName(无,“QFileDialog.getOpenFileName()”、“”、“所有文件(*);Python文件(*.py)”,选项=选项)
打印(文件名)
def run():
app=qgui应用程序(sys.argv)
app.setWindowIcon(QIcon(资源路径(“资产\\图像\\icon.ico”))
引擎=QQmlApplicationEngine()
engine.load(资源路径(“qml\\Window.qml”))
engine.quit.connect(app.quit)
如果不是engine.rootObjects():
返回-1
button=engine.rootObjects()[0]。findChild(QObject,“openButton”)
按钮。单击。连接(openFile)
return app.exec()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
sys.exit(run())
我还尝试通过
ApplicationWindow
而不是
None
,但随后出现了一个类型错误:

TypeError: getOpenFileName(parent: QWidget = None, caption: str = '', directory: str = '', filter: str = '', initialFilter: str = '', options: Union[QFileDialog.Options, QFileDialog.Option] = 0): argument 1 has unexpected type 'QWindow'
我认为这没有多大意义,因为
QMainWindow
继承了
QWidget

如何从我的
openFile()
函数显示对话框

编辑:为了完整起见,这里是我的.qml文件的精简版本

import QtQuick.Window 2.2
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick 2.3

ApplicationWindow {
    id: mainWindow
    visible: true
    width: 600  
    height: 400

    Item {
        anchors.top: titleBar.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        property bool isMainButtonFocused: false
        objectName: "openButton"
        signal clicked()

        Label {
            padding: 5
            text: "<b><font color='#fefefe'>Hello World</font></b>"
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenter: parent.horizontalCenter
            font.family: "Helvetica"
            font.pointSize: 9
            background: Rectangle {
                color: mouseAreaOpenFolderButton.containsMouse ? "#777777" : "#333333"
                border.width: isMainButtonFocused ? 2 : 1
                border.color: "#ffffff"
                radius: 5
            }

            MouseArea {
                id: mouseAreaOpenFolderButton
                anchors.fill: parent
                hoverEnabled: true
                onClicked: {
                    isMainButtonFocused = true
                    parent.parent.clicked()
                }
            }
        }
    }
}
导入QtQuick.Window 2.2 导入QtQuick.Controls 2.3 导入QtQuick.Layouts 1.3 导入QtQuick 2.3 应用程序窗口{ id:主窗口 可见:正确 宽度:600 身高:400 项目{ 锚。顶部:标题栏。底部 anchors.left:parent.left anchors.right:父项.right .bottom:parent.bottom 属性bool isMainButtonFocused:false objectName:“openButton” 点击信号() 标签{ 填充:5 文字:“你好,世界” anchors.verticalCenter:父级.verticalCenter anchors.horizontalCenter:父级.horizontalCenter font.family:“Helvetica” font.pointSize:9 背景:矩形{ 颜色:鼠标eaOpenFolderButton.containsMouse?”#777777:“#333333” 边框宽度:isMainButtonFocused?2:1 border.color:“#ffffff” 半径:5 } 鼠耳{ id:mouseAreaOpenFolderButton 锚定。填充:父级 hoverEnabled:true 再次点击:{ isMainButtonFocused=true parent.parent.clicked() } } } } }
错误非常明显:

  • 如果要使用QFileDialog之类的QWidget,则必须创建QApplication
  • 如果您要将QWidget传递给父对象,就像QFileDialog一样,那么该父对象必须是另一个QWidget,但ApplicationWindow不是QWidget,而是导致该错误的QWindow
另一个附加但更重要的错误是,您不应该从Python(或C++)访问QML对象,因为它的生命周期不同,因此可能会出现问题(例如,请参见),而应该创建一个QObject,在其中实现逻辑并将其作为项(使用qmlRegisterType)或上下文属性(通过setContextProperty)公开

考虑到上述情况,您应该使用FileDialog并将QObject作为上下文属性公开:

# ...
class Helper(QObject):
    @pyqtSlot(QUrl)
    def read_file(self, url):
        filename = url.toLocalFile()
        print(filename)


def run():
    app = QGuiApplication(sys.argv)
    app.setWindowIcon(QIcon(resource_path("assets\\images\\icon.ico")))

    engine = QQmlApplicationEngine()
    helper = Helper()
    engine.rootContext().setContextProperty("helper", helper)
    # ...
导入QtQuick.Window 2.2 导入QtQuick.Controls 2.3 导入QtQuick.Layouts 1.3 导入QtQuick 2.3 导入QtQuick.Dialogs 1.3 应用程序窗口{ id:主窗口 可见:正确 宽度:600 身高:400 项目{ 锚。顶部:标题栏。底部 anchors.left:parent.left anchors.right:父项.right .bottom:parent.bottom 属性bool isMainButtonFocused:false 标签{ 填充:5 文字:“你好,世界” anchors.verticalCenter:父级.verticalCenter anchors.horizontalCenter:父级.horizontalCenter font.family:“Helvetica” font.pointSize:9 背景:矩形{ 颜色:鼠标eaOpenFolderButton.containsMouse?”#777777:“#333333” 边框宽度:isMainButtonFocused?2:1 border.color:“#ffffff” 半径:5 } 鼠耳{ id:mouseAreaOpenFolderButton 锚定。填充:父级 hoverEnabled:true 再次点击:{ //isMainButtonFocused=true fileDialog.visible=true } } } } 文件对话框{ id:fileDialog 标题:“请选择一个文件” selectedNameFilter:“所有文件(*);Python文件(*.py)” 不接受:{ helper.read_文件(fileDialog.fileURL[0]) } } }
首先,将QML应用程序逻辑从QML中移出是一个非常糟糕的主意。更糟糕的想法是混合使用QtQuick和QWidgets。你为什么不改用它呢?至于问题-错误很明显-您必须使用
QApplication
而不是
QGuiApplication
。更多信息请参见讨论。我不想使用FileDialog,因为我想用Python检索结果,因为我需要从那里读出结果。然而我得出的结论是,这将是最简单的方法。。。
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick 2.3
import QtQuick.Dialogs 1.3

ApplicationWindow {
    id: mainWindow
    visible: true
    width: 600  
    height: 400

    Item {
        anchors.top: titleBar.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        property bool isMainButtonFocused: false

        Label {
            padding: 5
            text: "<b><font color='#fefefe'>Hello World</font></b>"
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenter: parent.horizontalCenter
            font.family: "Helvetica"
            font.pointSize: 9
            background: Rectangle {
                color: mouseAreaOpenFolderButton.containsMouse ? "#777777" : "#333333"
                border.width: isMainButtonFocused ? 2 : 1
                border.color: "#ffffff"
                radius: 5
            }

            MouseArea {
                id: mouseAreaOpenFolderButton
                anchors.fill: parent
                hoverEnabled: true
                onClicked: {
                    // isMainButtonFocused = true
                    fileDialog.visible = true
                    
                }
            }
        }
    }
    FileDialog {
        id: fileDialog
        title: "Please choose a file"
        selectedNameFilter: "All Files (*);;Python Files (*.py)"
        onAccepted: {
            helper.read_file(fileDialog.fileUrls[0])
        }
    }
}