Python Forum
[PyQt] [Solved]How to Run GUI MsgBox From Terminal Properly
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyQt] [Solved]How to Run GUI MsgBox From Terminal Properly
#1
Hello,

I'm trying to make an alert GUI that pops up/activates after a certain amount of time or when it's called by my program.

Right now I'm trying to get it to be a reminder alert popup. In my program, I go into the terminal and type in "Remind me to do stuff", then type in a time when I want to be reminded. After the specified amount of time, I want the GUI to trigger.

This is what I have so far.

BX_External_Functions.py
(This is where the reminders get set)
#-------------------------------------------------------------------------------------
#                                Reminder Function
#-------------------------------------------------------------------------------------
def setReminders(command):
    #------------------------------------------
    #           Add Reminder to Database
    #------------------------------------------
    #Connect to the database
    connection = sqlite3.connect(MainDatabase)
    cursor = connection.cursor()
    
    #Add the reminder to the reminders table
    cursor.execute("INSERT into Reminders (Reminder) VALUES(?)",(command,))
    connection.commit()
    connection.close() #Close the connection
    #------------------------------------------

    #Ask whether the user wants to pick a time or have Baxter do it
    results = "Would you like to pick a time for me to remind you, or should I do it?"
    autoTypeAnimation(results)
    speak(results)
    
    #User enters choice and their input gets converted to lowercase 
    choiceCommand = UserInput() #Take user's input
    choiceCommand=str(choiceCommand).lower() #Convert str cmd to lowercase

    #Scan through the youChoose() list to see if the user's input matches
    #If it does, have Baxter randomly choose a time to remind the user
    #Else, have the user enter the time they would like to be reminded 
    patterns = youChoose()
    if (choiceCommand in patterns):
        #Baxter picks a random time to remind you
        remindTimeHrs = random.uniform(0.5,5.0) #Range: 0.5hrs - 5hrs
        remindTimeHrs = round(remindTimeHrs,2) #Round RemindTimeHrs to 2 decimal places
        remindTimeSec = remindTimeHrs*3600 #Hrs->Sec
        results = "Ok, I will remind you to" + command + " in " + str(remindTimeHrs) + " hours"
        autoTypeAnimation(results)
        speak(results)
        t = threading.Timer(remindTimeSec, reminderPopup, args=(command,))
        t.start() #Start the timer
        
    else:
        #User picks the time to be reminded
        results = "When should I remind you to" + command +"?"
        autoTypeAnimation(results)
        speak(results)
        while True:
            autoTypeAnimation("Enter wait time (H:M:S) (Ex: 0:0:5 -> 5sec)")
            timestr = UserInput()
            if not timestr:
                break
            try:
                h,m,s = timestr.split(':')
                timestr = (int(datetime.timedelta(hours=int(h),minutes=int(m),seconds=int(s)).total_seconds()))
                t = threading.Timer(timestr, reminderPopup, args=(command,))
                results = "Ok, I will remind you to" + command + " in " + h + " Hours "+ m + " minutes " + s + " seconds"
                autoTypeAnimation(results)
                speak(results)
                t.start() #Start the timer
                break
            except ValueError:
                print("[green]Baxter: [red]Not a valid time input")


def reminderPopup(command):
    #------------------------------------------
    #           Remove Reminder to Database
    #------------------------------------------
    #Connect to the database
    connection = sqlite3.connect(MainDatabase)
    cursor = connection.cursor()
    
    #Add the reminder to the reminders table
    cursor.execute("DELETE FROM Reminders WHERE Reminder = ?",(command,))
    connection.commit()
    connection.close() #Close the connection
    #------------------------------------------

    global reminderMsg
    reminderMsg = command
    #Have a GUI/MsgBox popup to display the reminder. 
    from BX_GUI_MsgAlert import main
    main()
#-------------------------------------------------------------------------------------
BX_GUI_MsgAlert.py
(This is the Alert GUI)
#----------------------------------------------------------------------------------------------
#                                  Table Of Contents/Overview
#----------------------------------------------------------------------------------------------
# Imports

# GUI
# - Msg Display
# -- Button Actions
# --- Button Functions
# ---- Retranslate UI
# Run Program
#----------------------------------------------------------------------------------------------

#-------------------------------------------------------------------------------------
#                                  Imports
#-------------------------------------------------------------------------------------
import sys
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton, QMainWindow)
from PyQt5.QtCore import Qt, QMetaObject, QCoreApplication
from PyQt5.QtGui import QFont

class Ui_MsgAlert(QMainWindow):
    def __init__(self, parent = None):
        super(Ui_MsgAlert, self).__init__(parent)
        self.setObjectName("Alert")
        self.setFixedSize(800, 250)
        self.setStyleSheet("background-color: rgb(0, 0, 0);")
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.Header = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("Robo Sapien")
        font.setPointSize(25)
        font.setBold(True)
        font.setUnderline(False)
        font.setWeight(75)
        self.Header.setFont(font)
        self.Header.setStyleSheet("color: rgb(255, 0, 0);")
        self.Header.setAlignment(QtCore.Qt.AlignCenter)
        self.Header.setObjectName("Header")
        self.verticalLayout.addWidget(self.Header)
        self.Message = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("Runlion")
        font.setPointSize(15)
        font.setBold(True)
        font.setWeight(75)
        self.Message.setFont(font)
        self.Message.setStyleSheet("color: rgb(0, 255, 0);")
        self.Message.setAlignment(QtCore.Qt.AlignCenter)
        self.Message.setObjectName("Message")
        self.verticalLayout.addWidget(self.Message)
        self.AcknowledgeButton = QtWidgets.QPushButton(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("Robo Sapien")
        font.setPointSize(15)
        font.setBold(True)
        font.setWeight(75)
        self.AcknowledgeButton.setFont(font)
        self.AcknowledgeButton.setStyleSheet("background-color: rgb(255, 170, 0);\n"
"color: rgb(0, 0, 0);\n"
"border-style: outset;\n"
"border-width: 2px;\n"
"border-radius: 15px;\n"
"border-color: black;\n"
"padding: 4px;")
        self.AcknowledgeButton.setObjectName("AcknowledgeButton")
        self.verticalLayout.addWidget(self.AcknowledgeButton)
        self.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

        self.retranslateUi(self)
        QtCore.QMetaObject.connectSlotsByName(self)
    
#----------------------------------------------------------------------------------------------------
#                                      Msg Display
#----------------------------------------------------------------------------------------------------
        Title = self.Header 
        Message = self.Message

        from BX_External_Functions import reminderMsg

        Title.setText("Reminder Alert!")
        Message.setText("I was told to remind you to: " + reminderMsg)
#----------------------------------------------------------------------------------------------------
#                                      Button Actions
#----------------------------------------------------------------------------------------------------
        #------------------------------------------
        #               Acknowledge Button
        #------------------------------------------
        #When the Acknowledge button is clicked -> AcknowledgeClicked Function
        AcknowledgeButton = self.AcknowledgeButton
        AcknowledgeButton.clicked.connect(self.AcknowledgeClicked)
        #------------------------------------------

#----------------------------------
#       Acknowledge Function
#----------------------------------
    def AcknowledgeClicked(self):
        #Print in terminal for testing:
        #print("Acknowledge Button Clicked")
        self.close() #Quit this GUI
#----------------------------------

#----------------------------------------------------------------------------------------------------
#                                      Retranslate Ui
#----------------------------------------------------------------------------------------------------
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("MainWindow", "Alert"))
        self.Header.setText(_translate("MainWindow", "Reminder Alert!"))
        self.Message.setText(_translate("MainWindow", "I was told to remind you to:"))
        self.AcknowledgeButton.setText(_translate("MainWindow", "Acknowledge"))


#----------------------------------------------------------------------------------------------------
#                                       Run this Program
#----------------------------------------------------------------------------------------------------
def main():
    app = QApplication(sys.argv)
    win = Ui_MsgAlert()
    win.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
#----------------------------------------------------------------------------------------------------
This works (The GUI pops up, I can hit the Acknowledge button & it will exit the GUI, and I can still go back to terminal and enter more commands) but I get this message in the terminal:
Output:
WARNING: QApplication was not created in the main() thread.
So is there a way to do this properly so I don't get this message?

Thanks in advance.
Reply
#2
I don't really understand what you want to do there.
But here is an old reminder I once made. Maybe it helps a little.

You can display a reminder at a specific time and execute a command if you want.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from  PyQt5.QtCore import Qt, QTimer, QMetaObject, QSettings, QProcess, QSize, QRect
from PyQt5.QtWidgets import (QMessageBox, QApplication, QMainWindow, QPushButton, QGridLayout, 
                                QTextEdit, QLineEdit, QComboBox, QLabel, QWidget, QVBoxLayout)
from PyQt5.QtMultimedia import QSound
from PyQt5.QtGui import QIcon
import sys, datetime
import subprocess

class Message(QWidget):
    def __init__(self, title, message, parent=None):
        QWidget.__init__(self, parent)
        self.setLayout(QGridLayout())
        self.titleLabel = QLabel(title, self)
        self.titleLabel.setStyleSheet("color: #729fcf; font-size: 18px; font-weight: bold; padding: 0;")
        self.messageLabel = QLabel(message, self)
        self.messageLabel.setStyleSheet("color: #729fcf; font-size: 12px; font-weight: normal; padding: 0;")
        self.buttonClose = QPushButton(self)
        self.buttonClose.setIcon(QIcon.fromTheme("window-close"))
        self.buttonClose.setFlat(True)
        self.buttonClose.setFixedSize(32, 32)
        self.buttonClose.setIconSize(QSize(16, 16))
        self.layout().addWidget(self.titleLabel)
        self.layout().addWidget(self.messageLabel, 2, 0)
        self.layout().addWidget(self.buttonClose, 0, 1)

class Notification(QWidget):
    def __init__(self, parent = None):        
        super(QWidget, self).__init__(parent = None)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)      
        self.setStyleSheet("background: #000000; padding: 0;")
        self.mainLayout = QVBoxLayout(self)

    def setNotify(self, title, message, timeout):
        self.m = Message(title, message)
        self.mainLayout.addWidget(self.m)
        self.m.buttonClose.clicked.connect(self.onClicked)
        self.show()
        QTimer.singleShot(timeout, 0, self.closeMe)
        
    def closeMe(self):
        self.close()
        self.m.close()
    
    def onClicked(self):
        self.close()
        
class MyWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)

        self.entry = ""
        self.settings = QSettings("myReminder", "reminder")
        self.setObjectName("MainWindow")
        self.setFixedSize(250, 240)
        self.setWindowTitle("Reminder")

        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setStyleSheet(stylesheet(self))

        self.statusBar().showMessage("choose Time")
        
        self.process = QProcess()
        self.process.started.connect(lambda: print("process started"))
        self.process.finished.connect(lambda: print("process finished"))
        self.process.errorOccurred.connect(lambda: print("process eror"))

        self.hour = QComboBox()
        self.hour.addItem("00")
        self.hour.addItem("01")
        self.hour.addItem("02")
        self.hour.addItem("03")
        self.hour.addItem("04")
        self.hour.addItem("05")
        self.hour.addItem("06")
        self.hour.addItem("07")
        self.hour.addItem("08")
        self.hour.addItem("09")
        for x in range(10, 24):
            self.hour.addItem(str(x))

        self.minute = QComboBox()
        self.minute.addItem("00")
        self.minute.addItem("01")
        self.minute.addItem("02")
        self.minute.addItem("03")
        self.minute.addItem("04")
        self.minute.addItem("05")
        self.minute.addItem("06")
        self.minute.addItem("07")
        self.minute.addItem("08")
        self.minute.addItem("09")
        for x in range(10, 60):
            self.minute.addItem(str(x))

        h = str(datetime.datetime.now().time().strftime('%H'))
        m = str(datetime.datetime.now().time().strftime('%M'))

        self.hour.setCurrentIndex(self.hour.findText(h))
        self.minute.setCurrentIndex(self.minute.findText(m)+1)

        self.lblT = QLabel("Reminder at:   ")
        self.lbl = QLabel(":")

        self.cwid = self.addToolBar("Time")
        self.cwid.setMovable(False)
        self.cwid.addWidget(self.lblT)
        self.cwid.addWidget(self.hour)
        self.cwid.addWidget(self.lbl)
        self.cwid.addWidget(self.minute)

        btn_start = QPushButton(self)
        btn_start.setGeometry(10, 180, 80, 26)
        btn_start.setIcon(QIcon.fromTheme("player-play"))
        btn_start.setText("Start")
        btn_start.setObjectName("btn")
        btn_start.clicked.connect(self.button_start_clicked)

        btn_stop = QPushButton(self)
        btn_stop.setGeometry(160, 180, 80, 26)
        btn_stop.setIcon(QIcon.fromTheme("player-stop"))
        btn_stop.setText("Stop")
        btn_stop.setObjectName("btn_stop")
        btn_stop.clicked.connect(self.button_stop_clicked)

        self.message_entry = QTextEdit(self)
        self.message_entry.setAcceptRichText(True)
        self.message_entry.setGeometry(10, 40, 230, 100)
        self.message_entry.setPlaceholderText("Message")

        self.app_entry = QLineEdit(self)
        self.app_entry.setGeometry(10, 150, 230, 26)
        self.app_entry.setPlaceholderText("set command to start")
        self.app_entry.setToolTip("set command to start")

        self.msound = QSound(None)
        self.mysound = '/usr/share/sounds/speech-dispatcher/test.wav' 

        self.mymessage = ""

        self.timer = QTimer()
        self.timer.timeout.connect(self.update_label)

        self.readSettings()

        QMetaObject.connectSlotsByName(self)

    def updateEntry(self):
        mleft = self.hour.currentText()
        mright = self.minute.currentText()
        mtext = mleft + ":" + mright + ":00"
        self.entry = mtext
        self.message_entry.setFocus()

    def update_label(self):
        current_time = str(datetime.datetime.now().time().strftime('%H:%M:%S'))
        self.statusBar().showMessage(current_time + " / " + self.entry)
        if current_time == self.entry:
            self.timer.stop()
            self.msound.play(self.mysound)
            self.statusBar().showMessage("Reminder")          
            myapp = self.app_entry.text()
            if not myapp == "":
                print("starting", myapp)
                subprocess.Popen(myapp, stdout=subprocess.PIPE, shell=True)
            self.showNotification(self.message_entry.toPlainText())
            self.statusBar().showMessage("Timer gestoppt")
                
    def showNotification(self, message):
        self.notification = Notification()
        self.notification.setNotify("Reminder", message, 5000)
        r = QRect(self.x() + round(self.width() / 2) - round(self.notification.width() / 2), 
                                        self.y() + 26, self.notification.m.messageLabel.width() + 30, self.notification.m.messageLabel.height())
        self.notification.setGeometry(r)


    def button_start_clicked(self):
        self.updateEntry()
        self.statusBar().showMessage("Timer started ...")
        self.timer.start(1000)  #  1 second
        self.showMinimized()

    def button_stop_clicked(self):
        self.timer.stop()
        self.statusBar().showMessage("Timer stopped")
        self.msound.play(self.mysound)

    def msgbox(self, message):
        QMessageBox.information(None, "Information", "<h2>Reminder:</h2>\n\n" + message)
        self.showMaximized()

    def readSettings(self):
        print("reading settings")
        if self.settings.contains("geometry"):
            self.setGeometry(self.settings.value('geometry'))
        if self.settings.contains("message"):
            self.message_entry.setText(self.settings.value("message"))
        if self.settings.contains("myapp"):
            self.app_entry.setText(self.settings.value("myapp"))

    def saveSettings(self):
        print("saving settings")
        self.settings.setValue('geometry', self.geometry())
        self.settings.setValue('message', self.message_entry.toPlainText())
        self.settings.setValue('myapp', self.app_entry.text())

    def closeEvent(self,event):
        self.saveSettings()
        print("Goodbye ...")
        event.accept()

def stylesheet(self):
    return """

        QPushButton
        {
            font-size: 9pt;
            background: #729fcf;
        } 

        QPushButton::hover
        {
            color: #f3f3f3; 
        } 
        QTextEdit
        {
            font-size: 9pt;
            background: #729fcf;
            border: 1px solid #d3d7cf;
        } 

        QLineEdit
        {
            font-size: 9pt;
            background: #729fcf;
            border: 1px solid #d3d7cf;
        } 

        QToolBar
        {
            margin-left: 10px;
            margin-right: 10px;
            margin-top: 4px;
            font-size: 9pt;
            background: #729fcf;
            border: 1px solid #d3d7cf;
        } 

        QLabel
        {
            margin-left: 10px;
            margin-top: 4px;
        }

        QComboBox
        {
            width: 17px;
            padding-left: 5px;
            margin-top: 4px;
            font-size: 9pt;
            background: #729fcf;
        }

        QStatusBar
        {
            font-size: 7pt;
            color: #f3f3f3;
            padding-left: 10px;
         }
        QMainWindow
        {
            background: #729fcf;
        }
    """

if __name__ == "__main__":

    app = QApplication(sys.argv)
    main = MyWindow()
    main.show()
    sys.exit(app.exec_())
Reply
#3
(Oct-02-2022, 08:39 PM)Axel_Erfurt Wrote: I don't really understand what you want to do there.
But here is an old reminder I once made. Maybe it helps a little.

Ultimately, I just want to get rid of the WARNING: QApplication was not created in the main() thread. message so it doesn't popup in the terminal.
And thanks, I'll check out that old reminder you made, maybe it might help.
Reply
#4
Maybe it would be better if you make a github repository with an example database.

Your code snippets are mostly not comprehensible, since they often cannot be started due to a missing database or missing modules.
Reply
#5
I ended up doing:
import ctypes  
def Mbox(title, text, style):
    return ctypes.windll.user32.MessageBoxW(0, text, title, style)
Mbox('Your title', 'Your text', 1)
For a quick popup alert.

It's simple, it does the job, and it's what I was trying to accomplish before with PyQt.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyQt] [Solved]Add a SpinBox to MsgBox or Carry Variable Over? Extra 6 1,845 Jun-05-2022, 09:32 PM
Last Post: Extra

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020