an update to my code, based on the reply of Israel Unterman:
The Error-Class is now
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMainWindow
class Error(QtWidgets.QMainWindow):
reply = False
last_reply_id = None
last_id = 0
def __init__(self, error_code_string, parent=None):
super().__init__(parent)
QtWidgets.QMessageBox.warning(self, "Warnung", error_code_string, QtWidgets.QMessageBox.Ok)
id = give_id(self)
def give_id(self):
self.last_id += 1
return self.last_id
def give_reply(self):
if last_id == last_reply_id:
return self.reply
else:
return None
def set_reply(self, button, id):
if button in (QMessageBox.Ok, QMessageBox.Yes):
reply = True
else:
reply = False
self.last_reply_id = id
return reply
And the Test-Script comes with
from ErrorHandling import Error
Error('Test')
If I am using the normal Code (practically the same Code, just wrapped in a class) the message appears and then at the line
id = give_id(self)
the Code stops without any errormessage from python, just:
Process finished with exit code 1
If I use the test-script, there is nothing (No QMessageBox!) than this:
Process finished with exit code 1
If I debug the Code, init() gets the same Objects and variables, but
super().__init__(parent)
fails without any message.
So where is the mistake, or difference.
Here a shortend Version of the Class (it's too long to show all code here), from which the "Error" works nearly fine:
from ErrorHandling import Error
class MainWindow(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
# set some variables
self.create_layout()
def create_layout(self):
# creates a GUI using QWidgets with some Inputboxes and one button
[...]
def button_start_clicked(self):
Error('Check the input')
Here is the old question:
I have a problem regarding the setup of QtWidgets.QMessageBox.
All Code follows the description.
The ErrorHandling-Modul should give a message about an error.
If needed it may ask a question too.
The function ErrorMsg.errorMessage is called from other Moduls in case of an catched exception.
There will be more functions added.
If I run the code the following error occurs:
Connected to pydev debugger (build 145.1504)
Traceback (most recent call last):
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.1.4\helpers\pydev\pydevd.py", line 1531, in <module>
globals = debugger.run(setup['file'], None, None, is_module)
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.1.4\helpers\pydev\pydevd.py", line 938, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.1.4\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "C:/Quellcode/AllgTest.py", line 5, in <module>
reply = errm.errorMessage('Test')
File "C:/Quellcode\ErrorHandling.py", line 20, in errorMessage
msg_box.setIcon(QMessageBox.Warning)
TypeError: QMessageBox.setIcon(QMessageBox.Icon): first argument of unbound method must have type 'QMessageBox'
Process finished with exit code 1
I tried quite some variations and googled, but I have no idea what the problem is since I found some examples that are using the line
QMessageBox.setIcon(QMessageBox.Icon)
So where is my mistake?
And now the Code:
There is the following testscript to test my ErrorMsg-class
from ErrorHandling import ErrorMsg
errm = ErrorMsg()
reply = errm.errorMessage('Test')
And here is my ErrorHandling-Modul
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtWidgets import QMainWindow
class ErrorMsg(QMainWindow):
def __init__(self):
pass
def giveback(self,button):
if button in (QMessageBox.Ok, QMessageBox.Yes):
reply = True
else:
reply = False
return reply
def errorMessage(self, error_msg, buttons='OK'):
msg_box = QMessageBox
msg_box.setIcon(QMessageBox.Warning)
msg_box.setWindowTitle('Warning')
if buttons == 'OK':
msg_box.setStandardButtons(QMessageBox.Ok)
elif buttons == 'YesNo':
msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
else:
error_msg = 'Unknown Button >' + buttons + '<, use >OK< or >YesNo<'
raise ValueError(error_msg)
msg_box.setText(error_msg)
clicked_button = msg_box.exec()
return giveback(clicked_button)
Thanks for your help
James
You didn't create an object of the message box. To create an object use:
msg_box = QMessageBox()
But you don'y need to go through all this, since QMessageBox has static functions for showing messages, which you can call directly on the QMessageBox class. For example:
QMessageBox.warning(None, 'title', 'msg')
You also have some control over the butons, see QMessageBox
Related
I'm getting this error sometimes when I try to quit the Qt event loop. Using a code sample code,
from PyQt5 import QtCore, QtSerialPort
maxcounts = 10
counter = []
app = QtCore.QCoreApplication([])
serial_port = QtSerialPort.QSerialPort('COM3')
serial_port.setBaudRate(QtSerialPort.QSerialPort.Baud115200)
serial_port.open(QtCore.QIODevice.ReadWrite)
serial_port.setDataTerminalReady(1)
serial_port.setDataTerminalReady(0)
serial_port.setDataTerminalReady(1)
def handle_ready_read():
while serial_port.canReadLine():
resp = serial_port.readLine().data().decode().strip()
if len(counter) == maxcounts:
print('closing')
serial_port.setDataTerminalReady(0)
serial_port.setDataTerminalReady(1)
serial_port.setDataTerminalReady(0)
serial_port.close()
app.quit()
counter.append(1)
if resp == 'end':
print('closing')
serial_port.setDataTerminalReady(0)
serial_port.setDataTerminalReady(1)
serial_port.setDataTerminalReady(0)
serial_port.close()
app.quit()
serial_port.readyRead.connect(handle_ready_read)
app.exec_()
Any ideas it would output this error response?
ERROR:tornado.application:Exception in callback functools.partial(<function Kernel.enter_eventloop.<locals>.advance_eventloop at 0x000001DD311F8280>)
Traceback (most recent call last):
File "C:\Users\me\Anaconda3\lib\site-packages\tornado\ioloop.py", line 741, in _run_callback
ret = callback()
File "C:\Users\me\Anaconda3\lib\site-packages\ipykernel\kernelbase.py", line 314, in advance_eventloop
eventloop(self)
File "C:\Users\me\Anaconda3\lib\site-packages\ipykernel\eventloops.py", line 131, in loop_qt5
return loop_qt4(kernel)
File "C:\Users\me\Anaconda3\lib\site-packages\ipykernel\eventloops.py", line 117, in loop_qt4
kernel.app.setQuitOnLastWindowClosed(False)
AttributeError: 'QCoreApplication' object has no attribute 'setQuitOnLastWindowClosed'
I'm not using any windows. It doesn't happen every time though, after running once I usually don't see the error again.
Edit: It may be that setting spyder preference ipython console graphics backend as 'automatic' which may use Qt causes this error, instead of setting it as 'inline'. I found that using app = QtWidgets.QApplication([]) with app.setQuitOnLastWindowClosed(True) while commenting out app.quit() let's the plot show while using the automatic setting, without an error.
It seems that you are using some special environment(seems Spyder) where the developer assumes that you are using QGuiApplication or QApplication as an eventloop that have the setQuitOnLastWindowClosed method. A workaround is to create a class that inherits from QCoreApplication and has that method.
class CoreApplication(QtCore.QCoreApplication):
def setQuitOnLastWindowClosed(self, quit):
pass
maxcounts = 10
counter = []
app = CoreApplication([])
# ...
I'm writing a graphic application that gives a word after I press a key in my electric piano using a database.
I'm using PyGame, Tkinter and Sqlite.
The application is pretty simple and is almost finished,
but I'm stuck with that error between my piano.py and the frontEnd.py.
The thing is that I want a Label that writes what was the last key I pressed and put it on a canvas.
I know the problem is related to the 'while True' and already changed it with 'while idKey < 176' but with this change I receive the "noneType" error.
This is the current code in my file piano.py
piano.py
import pygame
import pygame.midi
from pygame.locals import *
class backPiano():
def funcPiano(self):
self = backPiano
pygame.init()
pygame.fastevent.init()
event_get = pygame.fastevent.get
event_post = pygame.fastevent.post
pygame.midi.init()
input_id = pygame.midi.get_default_input_id()
i = pygame.midi.Input( input_id )
while True:
events = event_get()
if i.poll():
midi_events = i.read(10)
idKey = midi_events[0][0][0]
if idKey == 176:
return False
And the code in my frontEnd (only the function with the problem):
frontEnd.py
from tkinter import *
from tkinter import ttk, font
import multiprocessing
import time
import os
from database import dictionary, path
from piano import backPiano
class frontEnd(Frame):
def __init__(self, parent):
self.backPiano = backPiano()
def capturePiano(self):
backPiano.funcPiano(self)
superPiano = StringVar()
superPiano.set(backPiano.funcPiano(self).idKey)
labelPiano.configure(textvariable=superPiano)
self.parent.update()
canvasWidth = 500
canvasHeight = 500
w = Canvas(parent, width=canvasWidth, height=canvasHeight)
w.place(x=monitorWidth/2,y=monitorHeight/2, anchor=CENTER)
w.create_image(canvasWidth/2, canvasHeight/2, image=img, anchor=CENTER)
labelPiano = Label(parent)
labelPiano.place(x=monitorWidth/2,y=monitorHeight/2)
In the line 'superPiano.set(backPiano.funcPiano(self).idKey)' I tried:
"superPiano.set(backPiano.idKey)"
But because the variable is inside a function it can't be called with that.
The exact error I have is this:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\admin\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Users\admin\Desktop\python\frontEnd.py", line 202, in <lambda>
command=lambda : capturePiano(self)).place(x=monitorWidth/9,y=monitorHeight/2,anchor=CENTER)
File "C:\Users\admin\Desktop\python\frontEnd.py", line 187, in capturePiano
superPiano.set(backPiano.funcPiano(self).idKey)
AttributeError: 'bool' object has no attribute 'idKey'
I can't upload all the code, but the error is in the While True but removing it destroys all my code because I need the loop.
Thank you very much (and sorry if I made grammar mistakes).
As the error message says: funcPiano is returning a boolean (True) so when you try to take the idKey it fails, because booleans don't have that.
I am using kivy to make a small music player but i have some issues with it. I am using a screen manager which will direct the user to either his libraries, or the entire tracks list. When one of the two is selected i want to find and load all the titles as buttons, to be played when pressed. Here's the basic track class:
class Track(Button):
path = 'C:/Users/...../tracks/'
def __init__(self,title,**kwargs):
self.title = title
super(Track,self).__init__(text=self.title,**kwargs)
def playTrack(self):
self.sound = SoundLoader.load(self.path+self.title)
self.sound.play()
also here is a music class that finds all the tracks in the directory and adds them to a list:
class mymusic():
path = 'C:/Users/...../tracks'
def __init__(self,**kwargs):
self.tracks=os.listdir(self.path)
print self.tracks
def loadTracks(self):
trackslist = []
for i in self.tracks:
trackslist.append(Track(i))
return trackslist
Finally, here is the code i use, that is supposed to create the buttons (the sm below is the screen manager, and root,libraries and music are subclasses of screen):
f = lambda obj: obj.playTrack()
Music = music(name='Music')
layout = BoxLayout()
Music.add_widget(layout)
sm.add_widget(root(name='Root'))
sm.add_widget(libraries(name='My libaries'))
sm.add_widget(Music)
musicobj = mymusic()
tracklist = musicobj.loadTracks()
for i in tracklist:
print i
i.bind(on_press=f(i))
This does not work. By running it i get the following error:
Traceback (most recent call last):
File "C:\Users\Vlassis\Desktop\test.py", line 108, in <module>
i.bind(on_press=f(i))
File "kivy\_event.pyx", line 430, in kivy._event.EventDispatcher.bind (kivy\_event.c:5903)
AssertionError: None is not callable
also the last track in the directory plays in the background. I can't figure out why. Is the logic behind the code correct? How should i go about doing this? Thanks in advance.
I have googled so much about this but did not find anything..
I have a custom exception class which invoked a QDialog to show the warning message..Now i am writing test for my application and in the test, i am sending the data which will make the application raise that exception and hence the dialog will appear.
But when i am running the test using pt.test, the dialog is appearing and when i close it, this is printed on my console..
E Failed: DID NOT RAISE
apptest.py:31: Failed
----------------------------- Captured stderr call -----------------------------
Traceback (most recent call last):
File "/home/kapil/mp3wav/mp3wav/application.py", line 62, in <lambda>
self.connect(self.conversionButton, SIGNAL("clicked()"), lambda: self.startConversion())
File "/home/kapil/mp3wav/mp3wav/application.py", line 79, in startConversion
self.__convert()
File "/home/kapil/mp3wav/mp3wav/application.py", line 86, in __convert
self.checkFile(__OUTFILE)
File "/home/kapil/mp3wav/mp3wav/application.py", line 105, in checkFile
raise FileTypeException(fileType, self)
mp3wav.exceptions.fileexception.FileTypeException
This is my test file..
import pytest
import os
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from mp3wav.application import Mp3WavApp
from mp3wav.exceptions.fileexception import FileTypeException
from mp3wav.exceptions.libraryexception import LibraryException
from mp3wav.exceptions.filenotexistexception import FileNotExistException
from mp3wav.exceptions.samefileexception import SameFileException
from mp3wav.exceptions.overwriteexception import OverWriteException
def windowTest(qtbot):
testapp = Mp3WavApp()
testapp.show()
qtbot.addWidget(testapp)
assert testapp.isVisible()
assert testapp.close()
#pytest.mark.qt_no_exception_capture
def fileTypeTest(qtbot, tmpdir):
testapp = Mp3WavApp()
qtbot.addWidget(testapp)
infile = tmpdir.mkdir("files").join("demo.mp3")
infile.write("something")
testapp.inputFileLine.setText(str(tmpdir.join("files", "demo.mp3")))
testapp.outputFileLine.setText(str(tmpdir.join('files')))
testapp.outputFileLineName.setText('demo.wave')
with pytest.raises(FileTypeException) :
qtbot.mouseClick(testapp.conversionButton, Qt.LeftButton)
Here is the custom exception
import os
import sys
from mp3wav.exceptions.errordialog import ErrorDialog
class FileTypeException(Exception):
def __init__(self, sid, parent=None):
super(FileTypeException, self).__init__()
filetype = "mp3"
if sid==2:
filetype = "wav"
errorMessage = "The Selected file is not "+filetype+\
"\nSelect the appropriate file"
if parent:
dialog = ErrorDialog(parent, errorMessage)
dialog.show()
dialog.exec_()
else:
print(errorMessage)
What i think is that it is failing because the dialog is appearing during the run of my test and i need to close it manually..But i don't know exactly why the test is failing..
Can anyone please guide me to the right path.. It will very much be appreciated..
I'm trying to make a little pinging tool with Scapy and PyQt4.
The code is fairly simple and all it does now is pinging an address the user can type in.
from PyQt4 import QtGui
import sys
from scapy.all import *
from scapy.sendrecv import sr, send
def q2s(qstr): return "%s" %qstr
class Application(QtGui.QMainWindow):
def __init__(self):
super(Application, self).__init__()
self.resize(1000,500)
self.centre()
self.initGui()
self.show()
def initGui(self):
self.ipAddress = QtGui.QLineEdit("1.1.1.1",self)
self.label = QtGui.QLabel("...")
self.label.move(50,100)
pingBtn = QtGui.QPushButton("Ping!", self)
pingBtn.move(50,50)
pingBtn.clicked.connect(self.ping)
def ping(self):
ip = q2s(self.ipAddress.text())
ans, unans = sr(IP(dst=ip)/ICMP(), timeout=1, verbose=0)
if ans:
self.label.setText("Host is up")
else:
self.label.setText("Host is down")
def centre(self):
screen = QtGui.QDesktopWidget().screenGeometry()
sizeNow = self.geometry()
self.move((screen.width() - sizeNow.width()) / 2,
(screen.height() - sizeNow.height()) / 2)
def run():
app = QtGui.QApplication(sys.argv)
GUI = Application()
sys.exit(app.exec_())
run()
However, when trying to ping an IP address an error is printed to the console.
Traceback (most recent call last):
File "Application.py", line 71, in ping
ans, unans = sr(IP(dst=ip)/ICMP(), timeout=1, verbose=0)
File "/usr/lib/python2.7/dist-packages/scapy/sendrecv.py", line 317, in sr
a,b=sndrcv(s,x,*args,**kargs)
File "/usr/lib/python2.7/dist-packages/scapy/sendrecv.py", line 129, in sndrcv
inp, out, err = select(inmask,[],[], remaintime)
select.error: (4, 'Unterbrechung w\xc3\xa4hrend des Betriebssystemaufrufs')
The last line means something like "Interruption during call of operating system".
I can not see what might be wrong about the program.
Using the send function instead of the sr function works somehow. So I think the problem might be that the application is waiting for a response. But I still don't know how to fix the error.
It's a bug in Scapy: an exception we want to catch when calling select() is different when in multi-thread environment.
A pull-request (#417) is currently examined (I'll update this answer when it has been merged), so you can check if the patch fixes this issue for you (I hope so!).