I am trying to test my PyQt app. I need to view results of my unittest in PyQt widget but when I run unittesting the app closes.
This is my code:
validation_test_app.py:
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest
import sys
import unittest
def get_size(url):
manager = QNetworkAccessManager()
response = manager.get(QNetworkRequest(QtCore.QUrl(r"https://" + url)))
event = QtCore.QEventLoop()
response.finished.connect(event.quit)
event.exec()
html = response.readAll()
size = html.size()
return size
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent = None):
super(MainWindow, self).__init__()
self.layout = QtWidgets.QVBoxLayout()
self.label = QtWidgets.QLabel("Checking tests...")
self.btn = QtWidgets.QPushButton("push")
self.btn.clicked.connect(self.btn_clicked)
self.layout.addWidget(self.label, alignment=QtCore.Qt.AlignCenter)
self.layout.addWidget(self.btn)
self.setLayout(self.layout)
def btn_clicked(self):
unittest.main(module="validation_test")
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
validation_test.py:
import unittest
from validation_test_app import get_size
class TestUrls(unittest.TestCase):
def test_1(self):
size = get_size("apps4all.ru")
self.assertEqual(size, 0)
def test_2(self):
size = get_size("google.com")
self.assertNotEqual(size, 0)
I want to view results of testing in QLabel, for example. Is it real to implement ?
This is a very late response, but since I had the same problem I figured I'd post. I think the solution is to add exit=False to the main call.
unittest.main(module="validation_test", exit=False)
Related
I want to show the results by clicking on the button, but if I press this code, the program will end in two seconds.
And 'pursent.ui' is just a widget that hasn't been set up.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType("pursent.ui")[0]
class MyWindow(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.btneve)
def btneve(self):
self.statusbar.showMessage((int(self.lineEdit_2.text())-int(self.lineEdit.text()))/int(self.lineEdit.text())*100)
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.show()
app.exec_()
void QStatusBar::showMessage(const QString &message, int timeout = 0)
Hides the normal status indications and displays the given message for the specified number of milli-seconds (timeout).
import sys
from PyQt5.QtWidgets import *
#from PyQt5 import uic
#form_class = uic.loadUiType("pursent.ui")[0]
class MyWindow(QMainWindow): #, form_class):
def __init__(self):
super().__init__()
# self.setupUi(self)
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
self.lineEdit = QLineEdit()
self.lineEdit_2 = QLineEdit()
self.pushButton = QPushButton('Button')
self.pushButton.clicked.connect(self.btneve)
self.statusbar = self.statusBar() # = StatusBar(self)
grid = QGridLayout(centralWidget)
grid.addWidget(self.lineEdit)
grid.addWidget(self.lineEdit_2)
grid.addWidget(self.pushButton)
def btneve(self):
self.statusbar.showMessage(str( # + str
(int(self.lineEdit_2.text())-int(self.lineEdit.text()))/int(self.lineEdit.text())*100)
)
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.show()
app.exec_()
I've written working example for vtkImageViewer:
But any image isn't rendered with vtkImageViewer2 or vtkResliceImageViewer. Have found example based on PyQt4+Python2.7 but wasn't able to get rendered images also (probably because of wrong versions of libraries).
Are there some examples in Python with these classes?
import sys
import vtk
from PyQt5 import QtCore, QtGui
from PyQt5 import QtWidgets
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent = None):
QtWidgets.QMainWindow.__init__(self, parent)
self.frame = QtWidgets.QFrame()
self.vl = QtWidgets.QVBoxLayout()
self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
self.vl.addWidget(self.vtkWidget)
pathDicomDir = "/path/to/dicom/data"
reader = vtk.vtkDICOMImageReader()
reader.SetDirectoryName(pathDicomDir)
reader.Update()
self.viewer = vtk.vtkImageViewer()
# self.viewer = vtk.vtkImageViewer2()
# self.viewer = vtk.vtkResliceImageViewer()
self.viewer.SetInputData(reader.GetOutput())
self.viewer.SetupInteractor(self.vtkWidget)
self.viewer.SetRenderWindow(self.vtkWidget.GetRenderWindow())
self.viewer.Render()
self.frame.setLayout(self.vl)
self.setCentralWidget(self.frame)
self.show()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
Just use
self.viewer = vtk.vtkImageViewer2()
and add
self.vtkWidget.Initialize()
after self.show()
I am trying to display an image from another thread in the main thread or possibly even a new thread. The problem is I cannot get the image to show anywhere else. I am using the thread _thread to download the image so it won't freeze the gui but I can't seem to get it out of there properly using QImage or QPixmap.
I know how to use strings and such in signals as shown in the example below but I am not sure how to send the image in a signal properly. I have tried using requests to grab an image url and send it to the main which works but I wasn't able to fetch the string in the main and then just download it there real fast either. That also is not a good option due to freezing the GUI momentarily.
This code is an example that shows that I can do all of the work and download the image in the main if I want to but would rather not.
import urllib2
from PyQt4 import QtGui
from PyQt4.QtCore import QThread, pyqtSignal
from PyQt4.QtGui import QApplication, QPixmap
import sys
class MainWindow(QtGui.QWidget):
def __init__(self):
super(self.__class__, self).__init__()
layout = QtGui.QVBoxLayout(self)
self._Button = QtGui.QPushButton()
self._Button.setObjectName("_Button")
self.line_edit = QtGui.QLineEdit()
self.line_edit.setObjectName("line_edit")
self.txt_box = QtGui.QTextEdit()
self.txt_box.setObjectName("txt_Box")
self.img_label = QtGui.QLabel()
self.img_label.setObjectName("img_label")
layout.addWidget(self._Button)
layout.addWidget(self.line_edit)
layout.addWidget(self.img_label)
layout.addWidget(self.txt_box)
self.pixmap = QPixmap()
self._thread = test_thread()
self._Button.clicked.connect(self.start_thread)
self.get_Text = self._thread.test_Signal.connect(self.line_edit.setText)
self.urls = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png'
data = urllib2.urlopen(self.urls).read()
self.pixmap.loadFromData(data)
self.img_label.setPixmap(self.pixmap)
def start_thread(self):
self._thread.start()
self._thread.test_Signal.connect(self.txt_box.setText)
class test_thread(QThread):
test_Signal = pyqtSignal(str)
def __init__(self):
super(test_thread, self).__init__()
def run(self):
string = 'This is a test string.'
self.test_Signal.emit(string)
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
And this code shows more of what I am looking to do.
import urllib2
from PyQt4 import QtGui
from PyQt4.QtCore import QThread, pyqtSignal
from PyQt4.QtGui import QApplication, QPixmap
import sys
class MainWindow(QtGui.QWidget):
def __init__(self):
super(self.__class__, self).__init__()
layout = QtGui.QVBoxLayout(self)
self._Button = QtGui.QPushButton()
self._Button.setObjectName("_Button")
self.line_edit = QtGui.QLineEdit()
self.line_edit.setObjectName("line_edit")
self.txt_box = QtGui.QTextEdit()
self.txt_box.setObjectName("txt_Box")
self.img_label = QtGui.QLabel()
self.img_label.setObjectName("img_label")
layout.addWidget(self._Button)
layout.addWidget(self.line_edit)
layout.addWidget(self.img_label)
layout.addWidget(self.txt_box)
self.pixmap = QPixmap()
self._thread = test_thread()
self._Button.clicked.connect(self.start_thread)
self.get_Text = self._thread.test_Signal.connect(self.line_edit.setText)
"...Send signal here and show image. EX:"
"...self._thread.image_Signal.connect(self.img_label.setPixmap)...."
"...or...."
def show_image_here(self):
"....Send image here after downloaded in thread...."
def start_thread(self):
self._thread.start()
self._thread.test_Signal.connect(self.txt_box.setText)
class test_thread(QThread):
test_Signal = pyqtSignal(str)
"....Example image signal...."
"....image_Signal = pyqtSignal()...."
def __init__(self):
super(test_thread, self).__init__()
self.pixmap = QPixmap()
def run(self):
string = 'This is a test string.'
self.test_Signal.emit(string)
self.urls = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png'
data = urllib2.urlopen(self.urls).read()
self.pixmap.loadFromData(data)
"....Not sure what to do here...."
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
Can somebody help me out? Thanks.
After looking around some more I came across this thread PySide threading and http downloading
I wish I had found it sooner because I did a lot of searching before my post. The person who answered that thread reclosedev also posted this in the comments:
https://pastebin.com/b4MD5jKh
Which helped me immensely to understand some things better. I used his code and slightly altered it to fit mine and it will work great for what I would like to do.
Here is my full working code using my original example for anyone out there that may find it useful.
import urllib2
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import QThread, pyqtSignal
from PyQt4.QtGui import QApplication
import sys
class MainWindow(QtGui.QWidget):
def __init__(self):
super(self.__class__, self).__init__()
layout = QtGui.QVBoxLayout(self)
self._Button = QtGui.QPushButton()
self._Button.setObjectName("_Button")
self.line_edit = QtGui.QLineEdit()
self.line_edit.setObjectName("line_edit")
self.txt_box = QtGui.QTextEdit()
self.txt_box.setObjectName("txt_Box")
self.img_label = QtGui.QLabel()
self.img_label.setObjectName("img_label")
self.imagepreview = ImagePreview()
layout.addWidget(self._Button)
layout.addWidget(self.line_edit)
layout.addWidget(self.img_label)
layout.addWidget(self.txt_box)
layout.addWidget(self.imagepreview)
self._thread = test_thread()
self._Button.clicked.connect(self.start_thread)
self._Button.clicked.connect(self.imagepreview.startDownload)
self.get_Text = self._thread.test_Signal.connect(self.line_edit.setText)
def start_thread(self):
self._thread.start()
self._thread.test_Signal.connect(self.txt_box.setText)
class test_thread(QThread):
test_Signal = pyqtSignal(str)
def __init__(self):
super(test_thread, self).__init__()
def run(self):
string = 'This is a test string.'
self.test_Signal.emit(string)
class DownloadThread(QtCore.QThread):
data_downloaded = pyqtSignal()
def __init__(self, url):
QtCore.QThread.__init__(self)
self.url = url
self._data = None
def run(self):
self._data = urllib2.urlopen(self.url).read()
self.data_downloaded.emit()
def get_data(self):
return self._data
class ImagePreview(QtGui.QWidget):
def __init__(self, parent=None):
super(ImagePreview, self).__init__(parent)
self.setMinimumSize(50, 50)
self.pixmap = None
def paintEvent(self, paintEvent):
painter = QtGui.QPainter(self)
if (self.pixmap):
painter.drawPixmap(0, 0, self.pixmap)
def startDownload(self):
self.download_thread = DownloadThread('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png')
self.download_thread.start()
self.download_thread.data_downloaded.connect(self.ondownloadFinished)
def ondownloadFinished(self):
self.paintImage()
print("download finished")
def paintImage(self):
print("Painting")
pixmap = QtGui.QPixmap()
pixmap.loadFromData(self.download_thread.get_data())
self.setPixmap(pixmap)
def setPixmap(self, pixmap):
self.pixmap = pixmap
self.setMinimumSize(pixmap.width(), pixmap.height())
self.update()
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
I'm trying to use QProcess and read the stdout to a QTextEdit initiated by a button. How can I adapt this example to do so? Do I have to call a separate class for the QProcess?
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
class MyQProcess(QProcess):
def __init__(self):
#Call base class method
QProcess.__init__(self)
#Create an instance variable here (of type QTextEdit)
self.edit = QTextEdit()
self.edit.setWindowTitle("QTextEdit Standard Output Redirection")
self.edit.show()
#Define Slot Here
#pyqtSlot()
def readStdOutput(self):
self.edit.append(QString(self.readAllStandardOutput()))
def main():
app = QApplication(sys.argv)
qProcess = MyQProcess()
qProcess.setProcessChannelMode(QProcess.MergedChannels);
qProcess.start("ldconfig -v")
QObject.connect(qProcess,SIGNAL("readyReadStandardOutput()"),qProcess,SLOT("readStdOutput()"));
return app.exec_()
if __name__ == '__main__':
main()
Use QPushButton to make a button.
Use QPushButton.clicked.connect to bind event.
For example:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MyWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.edit = QTextEdit()
self.edit.setWindowTitle("QTextEdit Standard Output Redirection")
self.button = QPushButton('Run ldconfig')
self.button.clicked.connect(self.onClick)
layout = QVBoxLayout(self)
layout.addWidget(self.edit)
layout.addWidget(self.button)
#pyqtSlot()
def readStdOutput(self):
self.edit.append(QString(self.proc.readAllStandardOutput()))
def onClick(self):
self.proc = QProcess()
self.proc.start("echo hello")
self.proc.setProcessChannelMode(QProcess.MergedChannels);
QObject.connect(self.proc, SIGNAL("readyReadStandardOutput()"), self, SLOT("readStdOutput()"));
def main():
app = QApplication(sys.argv)
win = MyWindow()
win.show()
return app.exec_()
if __name__ == '__main__':
main()
I'm trying to use a QPushButton to call a function that opens a new instance of QWebView. Works but as soon as the window opens it closes again.
I've read this - PyQt window closes immediately after opening but I don't understand how to reference the window to keep it open.
import sys
from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.QtWebKit import QWebSettings
from PyQt4.QtNetwork import QNetworkAccessManager
from PyQt4.QtNetwork import *
UA_STRING = """Test Test Test"""
vidurl = ("empty")
def web1():
class YWebPage(QtWebKit.QWebPage):
def __init__(self):
super(QtWebKit.QWebPage, self).__init__()
def userAgentForUrl(self, url):
return UA_STRING
class Browser(QtGui.QMainWindow): # "Browser" window
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.resize(800,600) # Viewport size
self.centralwidget = QtGui.QWidget(self)
self.html = QtWebKit.QWebView()
def browse(self):
self.webView = QtWebKit.QWebView()
self.yPage = YWebPage()
self.webView.setPage(self.yPage)
self.webView.load(QtCore.QUrl(vidurl)) # Video URL
self.webView.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled,True) # Enables flash player
self.webView.show()
x = Browser()
# QNetworkProxy.setApplicationProxy(QNetworkProxy(QNetworkProxy.HttpProxy, "proxy.example.com", 8080)) # Proxy setting
x.browse()
def main(): # Dialog window
app = QtGui.QApplication(sys.argv)
w = QtGui.QWidget()
w.resize(200, 450)
w.setFixedSize(200, 350)
w.move(300, 300)
w.setWindowTitle('U-bot 0.1')
# Setup GUI
# Start Button
w.__button = QtGui.QPushButton(w)
w.__button.clicked.connect(lambda: web1())
# Text area
w.__qle = QtGui.QLineEdit(w)
w.__qle.setText ("http://")
vidurl = w.__qle.text # Get video url from user
# Images
pixmap1 = QtGui.QPixmap("ubot.png")
lbl1 = QtGui.QLabel(w)
lbl1.resize(200, 150)
lbl1.setPixmap(pixmap1)
lbl1.setScaledContents(True)
w.__button.setText('Start')
layout = QtGui.QVBoxLayout()
layout.addStretch(1)
layout.addWidget(w.__qle)
layout.addWidget(w.__button)
w.setLayout(layout)
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
app.exec_()
Create a MainWindow class that keeps a list of open Browsers, and every time when you open a browser, just add it to the list. And when a browser window closes, it will remove itself from the list, see closeEvent.
import sys
from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.QtWebKit import QWebSettings
from PyQt4.QtNetwork import QNetworkAccessManager
from PyQt4.QtNetwork import *
UA_STRING = """Test Test Test"""
vidurl = ("empty")
class YWebPage(QtWebKit.QWebPage):
def __init__(self):
super(YWebPage, self).__init__()
def userAgentForUrl(self, url):
return UA_STRING
class Browser(QtGui.QMainWindow): # "Browser" window
def __init__(self, main, url):
QtGui.QMainWindow.__init__(self)
self.main = main
self.resize(800,600) # Viewport size
self.webView = QtWebKit.QWebView()
self.setCentralWidget(self.webView)
self.yPage = YWebPage()
self.webView.setPage(self.yPage)
self.webView.load(QtCore.QUrl(url)) # Video URL
self.webView.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, True) # Enables flash player
def closeEvent(self, event):
self.main.browsers.remove(self)
super(Browser, self).closeEvent(event)
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.browsers = []
self.resize(200, 450)
self.setFixedSize(200, 350)
self.move(300, 300)
self.setWindowTitle('U-bot 0.1')
# Setup GUI
# Start Button
self.__button = QtGui.QPushButton('Start')
self.__button.clicked.connect(self.open)
# Text area
self.__qle = QtGui.QLineEdit()
self.__qle.setText("http://")
# Images
pixmap1 = QtGui.QPixmap("ubot.png")
lbl1 = QtGui.QLabel()
lbl1.resize(200, 150)
lbl1.setPixmap(pixmap1)
lbl1.setScaledContents(True)
layout = QtGui.QVBoxLayout()
layout.addStretch(1)
layout.addWidget(self.__qle)
layout.addWidget(self.__button)
self.setLayout(layout)
def open(self):
b = Browser(self, self.__qle.text())
b.show()
self.browsers.append(b)
def main():
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
To keep a reference to a QObject, you can either keep the variable in scope, or add it as the child of another QObject which variable already stays in scope.
And for QWidget, the parent should also be a QWidget, so, in your case, you'd want to make w as the parent of all your QMainWindows.
def web1(parent):
...
class Browser(QtGui.QMainWindow): # "Browser" window
def __init__(self, parent):
QtGui.QMainWindow.__init__(self, parent)
...
def main():
...
w.__button.clicked.connect(lambda: web1(w))
This also avoid maintaining manually a list of opened windows, since the object hierarchy can do that for you.
PS: The child windows are shown as toplevel windows and not inside the w window, because QMainWindow (and QDialog) has the Qt::Window flag set by default.