How can I show a PyQt modal dialog and get data out of its controls once its closed?
Asked Answered
D

3

20

For a built-in dialog like QInputDialog, I've read that I can do this:

text, ok = QtGui.QInputDialog.getText(self, 'Input Dialog', 'Enter your name:')

How can I emulate this behavior using a dialog that I design myself in Qt Designer? For instance, I would like to do:

my_date, my_time, ok = MyCustomDateTimeDialog.get_date_time(self)
Demagnetize answered 12/8, 2013 at 21:12 Comment(0)
E
32

Here is simple class you can use to prompt for date:

class DateDialog(QDialog):
    def __init__(self, parent = None):
        super(DateDialog, self).__init__(parent)

        layout = QVBoxLayout(self)

        # nice widget for editing the date
        self.datetime = QDateTimeEdit(self)
        self.datetime.setCalendarPopup(True)
        self.datetime.setDateTime(QDateTime.currentDateTime())
        layout.addWidget(self.datetime)

        # OK and Cancel buttons
        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal, self)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addWidget(buttons)

    # get current date and time from the dialog
    def dateTime(self):
        return self.datetime.dateTime()

    # static method to create the dialog and return (date, time, accepted)
    @staticmethod
    def getDateTime(parent = None):
        dialog = DateDialog(parent)
        result = dialog.exec_()
        date = dialog.dateTime()
        return (date.date(), date.time(), result == QDialog.Accepted)

and to use it:

date, time, ok = DateDialog.getDateTime()
Ericaericaceous answered 13/8, 2013 at 7:6 Comment(3)
Can you explain why you use the @staticmethod decorator, and why you chose to instantiate the DateDialog class within the DateDialog class definition? I found this a bit confusing.Bathos
@Bathos True. You can use straightforward function to create the dialog and get the result which is better (if you don't need to reuse the dialog class).Also it could return just the date object and return None or throw exception if dialog was canceled (not sure what is the right solution in Python).Ericaericaceous
For anyone that doesn't know, QDialog can be imported as follows: from PyQt4.QtGui import QDialog (assuming you are using PyQt version 4)Akeylah
R
28

I tried to edit the answer of hluk with the changes below but it got rejected, not sure why because it got some clear bugs as far is I can see.

bugfix 1: removed self. from self.layout.addWidget(self.buttons)

bugfix 2: connected OK and Cancel buttons to its correct actions

enhancement: made the code ready to run by including the imports and improved the run example

from PyQt4.QtGui import QDialog, QVBoxLayout, QDialogButtonBox, QDateTimeEdit, QApplication
from PyQt4.QtCore import Qt, QDateTime

class DateDialog(QDialog):
    def __init__(self, parent = None):
        super(DateDialog, self).__init__(parent)

        layout = QVBoxLayout(self)

        # nice widget for editing the date
        self.datetime = QDateTimeEdit(self)
        self.datetime.setCalendarPopup(True)
        self.datetime.setDateTime(QDateTime.currentDateTime())
        layout.addWidget(self.datetime)

        # OK and Cancel buttons
        self.buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal, self)
        layout.addWidget(self.buttons)

        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)

    # get current date and time from the dialog
    def dateTime(self):
        return self.datetime.dateTime()

    # static method to create the dialog and return (date, time, accepted)
    @staticmethod
    def getDateTime(parent = None):
        dialog = DateDialog(parent)
        result = dialog.exec_()
        date = dialog.dateTime()
        return (date.date(), date.time(), result == QDialog.Accepted)

and to use it:

app = QApplication([])
date, time, ok = DateDialog.getDateTime()
print("{} {} {}".format(date, time, ok))
app.exec_()
Rollandrollaway answered 17/9, 2014 at 13:35 Comment(0)
S
0

For completeness, here's a PyQt5 version with updated imports:

from PyQt5.QtWidgets import (
    QDialog, QVBoxLayout, QDateTimeEdit, QDialogButtonBox, QApplication)
from PyQt5.QtCore import QDateTime, Qt


class DateDialog(QDialog):
    def __init__(self, parent=None):
        super(DateDialog, self).__init__(parent)

        layout = QVBoxLayout(self)

        # nice widget for editing the date
        self.datetime = QDateTimeEdit(self)
        self.datetime.setCalendarPopup(True)
        self.datetime.setDateTime(QDateTime.currentDateTime())
        layout.addWidget(self.datetime)

        # OK and Cancel buttons
        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal, self)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addWidget(buttons)

    # get current date and time from the dialog
    def dateTime(self):
        return self.datetime.dateTime()

    # static method to create the dialog and return (date, time, accepted)
    @staticmethod
    def getDateTime(parent=None):
        dialog = DateDialog(parent)
        result = dialog.exec_()
        date = dialog.dateTime()
        return (date.date(), date.time(), result == QDialog.Accepted)

To run I used:

app = QApplication([])
date, time, ok = DateDialog.getDateTime()
print("{} {} {}".format(date, time, ok))

Leaving out app.exec_(), so that the app would exit after printing.

Spates answered 29/9, 2023 at 17:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.