简体   繁体   中英

Add widget (QCheckBox) to QFileDialog in PyQt5 (Python) not working

I would like to add a QCheckBox to a QFileDialog. I would like to use the static method QFileDialog.getSaveFileName() to show the dialog.

I have found several similar questions, all in c++:

  1. How to add checkbox to QFileDialog window in QT3?
  2. Adding a widget in QFileDialog
  3. https://www.qtcentre.org/threads/42858-Creating-a-Custom-FileOpen-Dialog
  4. https://forum.qt.io/topic/103964/add-checkbox-to-qfiledialog/7

I did my best to translate these discussions to python, but have not gotten to the solution yet. My code runs, but the checkbox does not show up, even when I use QFileDialog.DontUseNativeDialog.

This is how I am subclassing QFileDialog:

from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtWidgets import QCheckBox

class ChkBxFileDialog(QFileDialog):
    def __init__(self, chkBxTitle=""):
        super().__init__()
        self.setOption(QFileDialog.DontUseNativeDialog)
        chkBx = QCheckBox(chkBxTitle)
        self.layout().addWidget(chkBx)
    #end __init__
#end ChkBxFileDialog

I have run this in two ways.

Option 1 (with extra QFileDialog.DontUseNativeDialog):

import sys    
from PyQt5.QtWidgets import QApplication
if __name__ == "__main__":
        app = QApplication(sys.argv)
        fileDialog = ChkBxFileDialog(chkBxTitle="Chkbx")
        fileName = fileDialog.getSaveFileName(filter='*.txt', initialFilter='*.txt',
                                              options=QFileDialog.DontUseNativeDialog)[0]
        sys.exit(app.exec_())

Option 2 (without extra QFileDialog.DontUseNativeDialog):

import sys    
from PyQt5.QtWidgets import QApplication    
if __name__ == "__main__":
        app = QApplication(sys.argv)
        fileDialog = ChkBxFileDialog(chkBxTitle="Chkbx")
        fileName = fileDialog.getSaveFileName(filter='*.txt', initialFilter='*.txt')[0]
        sys.exit(app.exec_())

The checkbox doesn't show with either option. Option 1 uses different window styling. Option 2 shows the typical PyQt QFileDialog.

Does anyone know what I am missing?

The problem is that getSaveFileName is a static method so they do not inherit from ChkBxFileDialog and therefore do not have the custom behavior.

There are 2 options:

  • Don't use getSaveFileName but implement the logic using QFileDialog directly:

     import sys from PyQt5.QtWidgets import QApplication, QCheckBox, QDialog, QFileDialog class ChkBxFileDialog(QFileDialog): def __init__(self, chkBxTitle="", filter="*.txt"): super().__init__(filter=filter) self.setSupportedSchemes(["file"]) self.setOption(QFileDialog.DontUseNativeDialog) self.setAcceptMode(QFileDialog.AcceptSave) self.selectNameFilter("*.txt") chkBx = QCheckBox(chkBxTitle) self.layout().addWidget(chkBx) def main(): app = QApplication(sys.argv) dialog = ChkBxFileDialog() if dialog.exec_() == QDialog.Accepted: filename = dialog.selectedUrls()[0].toLocalFile() print(filename) if __name__ == "__main__": main()
  • Use some trick to get the QFileDialog instance, such as getting all the topLevels and verifying that it is a QFileDialog.

     import sys from functools import partial from PyQt5.QtCore import QTimer from PyQt5.QtWidgets import QApplication, QCheckBox, QDialog, QFileDialog def add_checkbox(chkBxTitle): for tl in QApplication.topLevelWidgets(): if isinstance(tl, QFileDialog): tl.setOption(QFileDialog.DontUseNativeDialog) chkBx = QCheckBox(chkBxTitle) tl.layout().addWidget(chkBx) def main(): app = QApplication(sys.argv) QTimer.singleShot(1000, partial(add_checkbox, "")) fileName, _ = QFileDialog.getSaveFileName( filter="*.txt", initialFilter="*.txt", options=QFileDialog.DontUseNativeDialog ) if __name__ == "__main__": main()

I would like to use the static method QFileDialog.getSaveFileName() to show the dialog

That's not possible. The static method as is defined in the C++ code knows nothing about your derived class, so it will create an instance of the base class, which doesn't contain your modifications. You have to explicitly instantiate your derived class, call exec() on the instance, check the return code and possibly call its selectedFiles() method to see what files were selected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM