Using functions from a class in another file to a class in my second file, python3 - python-3.4

I have two python files, one is the gui, the other contains all of the functions, say i have a class named Backend like in the code below, and one of its functions is "print1(self)", and i want to use that "print1" function inside of the second file in the class named retranslateUi(self, Form), how would i do it?
First file
__author__ = 'Richard'
import sqlite3
conn = sqlite3.connect('realscheduler.db')
c = conn.cursor()
c.execute('pragma foreign_keys = ON;')
class Backend:
def print1(self):
print('Works')
Second file
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.4.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.label = QtWidgets.QLabel(Form)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem1)
self.horizontalLayout.addLayout(self.verticalLayout)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "Labellabellabel"))
self.pushButton.setText(_translate("Form", "Print"))

First you should create a main entry point to the application like so. I will call it app.py and the generated Qt Designer file view.py for this example:
from PyQt5.QtWidgets import (QMainWindow, QApplication)
# importing the GUI from the designer file
from view import Ui_MainWindow
# importing the database file Backend class
from database import Backend
class Main(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.setupUi(self)
# this will connect your push button the the function
self.pushButton.clicked.connect(Backend.print1)
if __name__ == "__main__":
import sys
QCoreApplication.setApplicationName("app name")
QCoreApplication.setApplicationVersion("app version")
QCoreApplication.setOrganizationName("Your name")
QCoreApplication.setOrganizationDomain("Your URL")
app = QApplication(sys.argv)
form = Main()
form.show()
sys.exit(app.exec_())
PyQt follows the Model-View architecture so this is a nice way to bind your functionality / data away from the graphical components of the application.

You have to import the first file into the second one as import first_filename as t then create class object p=t.classname then use any function you want which is declared in the class

Related

Empty image in QClipboard [duplicate]

I'm trying to run a simple PyQt5 application on Linux, the code is as follows:
#!/usr/bin/python
import sys
from PyQt5.QtWidgets import QApplication, QWidget
def main():
app = QApplication(sys.argv)
w = QWidget()
w.resize(250, 150)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
mime = app.clipboard().mimeData()
print(mime.hasImage()) # True
print(mime.imageData()) # None
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Before running it, I copied an image into the clipboard, so mime.hasImage() should return True. No problem, that's also the case. But what's weird is, mime.imageData() sometimes returns None. that shouldn't happen. mime.imageData() should contain the image that I copied instead of None. Is there anything wrong with the code?
By the way, this seems to only happen on Linux, mime.imageData() never returns None on Windows. I'm using python3
That hasImage() returns True does not imply that imageData() returns a QImage since it only indicates that the user copied an image to the clipboard, and in what format do I copy the image? Well, it could be png, jpg, etc or it could provide the url for the client application to download or html to insert it into the client application and then obtain the image by rendering the HTML.
So in general the application from which the image was copied is responsible for the sending format and that there is no restrictive standard for that format but there are common formats.
The following example shows the logic to handle the images that come from urls and HTML:
#!/usr/bin/python
import sys
from functools import cached_property
from PyQt5.QtCore import pyqtSignal, QObject, QUrl
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
from PyQt5.QtGui import QGuiApplication, QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from bs4 import BeautifulSoup
class ImageDownloader(QObject):
finished = pyqtSignal(QImage)
def __init__(self, parent=None):
super().__init__(parent)
self.manager.finished.connect(self.handle_finished)
#cached_property
def manager(self):
return QNetworkAccessManager()
def start_download(self, url):
self.manager.get(QNetworkRequest(url))
def handle_finished(self, reply):
if reply.error() != QNetworkReply.NoError:
print("error: ", reply.errorString())
return
image = QImage()
image.loadFromData(reply.readAll())
self.finished.emit(image)
class ClipboardManager(QObject):
imageChanged = pyqtSignal(QImage)
def __init__(self, parent=None):
super().__init__(parent)
QGuiApplication.clipboard().dataChanged.connect(
self.handle_clipboard_datachanged
)
self.downloader.finished.connect(self.imageChanged)
#cached_property
def downloader(self):
return ImageDownloader()
def handle_clipboard_datachanged(self):
mime = QGuiApplication.clipboard().mimeData()
if mime.hasImage():
image = mime.imageData()
if image is not None:
self.imageChanged.emit(image)
elif mime.hasUrls():
url = mime.urls()[0]
self.downloader.start_download(urls[0])
elif mime.hasHtml():
html = mime.html()
soup = BeautifulSoup(html, features="lxml")
imgs = soup.findAll("img")
if imgs:
url = QUrl.fromUserInput(imgs[0]["src"])
self.downloader.start_download(url)
else:
for fmt in mime.formats():
print(fmt, mime.data(fmt))
def main():
app = QApplication(sys.argv)
label = QLabel(scaledContents=True)
label.resize(250, 150)
label.move(300, 300)
label.setWindowTitle("Simple")
label.show()
manager = ClipboardManager()
manager.imageChanged.connect(
lambda image: label.setPixmap(QPixmap.fromImage(image))
)
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Qt Designer Storing and Parsing User Input from Line Edit using Python to Robot Operating System (ROS)

I am currently trying to create a GUI that allows users to type in whatever words they want to be translated into R2-D2's voice.
I have used Qt 5 Designer to create a user input using Line Edit and a button that will publish the user input to a specified topic in ROS. I have also converted it into a python file using pyuic5 -o as r2d2_sound_control.py and I have a main file called main_r2d2_sound_control.py that I will run to initialise the GUI.
How do you store and parse a string from Line Edit using python? I do not know how to declare the string from the user input and parse it when the button is clicked. I'm using pyqt 4
Thank you in advance.
Link to R2-D2 voice package in GitHub https://github.com/koide3/ros2d2
Contents of r2d2_sound_control.py:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'r2d2_sound_control.ui'
#
# Created by: PyQt5 UI code generator 5.10.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(505, 114)
self.pushButton_speak = QtWidgets.QPushButton(Dialog)
self.pushButton_speak.setGeometry(QtCore.QRect(300, 40, 89, 25))
self.pushButton_speak.setObjectName("pushButton_speak")
self.lineEdit_speak = QtWidgets.QLineEdit(Dialog)
self.lineEdit_speak.setGeometry(QtCore.QRect(60, 40, 201, 25))
self.lineEdit_speak.setObjectName("lineEdit_speak")
self.retranslateUi(Dialog)
self.pushButton_speak.clicked.connect(Dialog.clicked_speak)
self.lineEdit_speak.returnPressed.connect(Dialog.clicked_speak)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton_speak.setText(_translate("Dialog", "Say Out"))
Contents of main_r2d2_sound_control.py
#! /usr/bin/python3
# -*- coding: utf-8 -*-
# GUI
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
#Import the automatically generated file
from r2d2_sound_control import Ui_Dialog
# ROS
import rospy
from std_msgs.msg import String
class Test(QDialog):
def __init__(self,parent=None):
# GUI
super(Test, self).__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
# ROS pub settings
self.r2d2_sound_controller_String = String()
self.pub_r2d2_sound_controller_speak = rospy.Publisher('/ros2d2_node/speak',String,queue_size=10)
def speak_content(self):
self.input = string(lineEdit_speak)
self.lineEdit_speak.setText(self.text())
def clicked_speak(self):
"""
The slot name specified in Qt Designer.
Write the process you want to execute with the "Say Out" button.
"""
self.r2d2_sound_controller_String.data = text()
self.pub_r2d2_sound_controller_speak.publish(self.r2d2_sound_controller_String)
self.r2d2_sound_controller_String.data = ''
if __name__ == '__main__':
rospy.init_node('r2d2_sound_talker')
app = QApplication(sys.argv)
window = Test()
window.show()
sys.exit(app.exec_())
I have managed to fix it thanks to my friend. I have made the following changes to main_r2d2_sound_control.py
#! /usr/bin/python3
# -*- coding: utf-8 -*-
# GUI
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
#Import the automatically generated file
from r2d2_head_gripper_sound import Ui_Dialog
# ROS
import rospy
from std_msgs.msg import String
class Test(QDialog):
def __init__(self,parent=None):
# GUI
super(Test, self).__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
# ROS pub settings
self.r2d2_sound_controller_String = String()
self.pub_r2d2_sound_controller_speak = rospy.Publisher('/ros2d2_node/speak',String,queue_size=10)
self.r2d2_sound_controller_String.data = ''
def clicked_speak(self):
"""
The slot name specified in Qt Designer.
Write the process you want to execute with the "Say Out" button.
"""
text = self.ui.lineEdit_speak.text()
self.r2d2_sound_controller_String.data = text
self.pub_r2d2_sound_controller_speak.publish(self.r2d2_sound_controller_String)
if __name__ == '__main__':
rospy.init_node('r2d2_head_and_gripper_talker')
app = QApplication(sys.argv)
window = Test()
window.show()
sys.exit(app.exec_())

PyQt: connecting slots with custom objects via Qt Designer

I have a PyQt widget that sends signals with numpy.ndarray data. And I have another PyQt widget that has a slot with numpy.ndarray data.
Both widget are located on my main window, that is compiled from *.ui file. The widgets are set as promoted widgets.
Cannot I somehow connect the signal and slot in Qt Creator?
Just now it gives me the next error:
TypeError: C++ type 'ndarray' is not supported as a slot argument type
Reason for this is Qt only support the datatype defined in QMetaType passed as argument of signal, looks here http://pyqt.sourceforge.net/Docs/PyQt4/qmetatype.html#Q_DECLARE_METATYPE
According to ekhumoro's POST, I update the following code, it should work for PyQt4, not tested on PyQt5.
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from numpy import *
class MyThread(QThread):
mysignal = pyqtSignal(ndarray)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
def run(self):
while True:
QThread.msleep(100)
self.mysignal.emit(array((1, 2, 3, 4)))
class MyWidget(QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
self.thread = MyThread()
self.thread.mysignal.connect(self.handleSignal)
self.thread.start()
def handleSignal(self, data):
print data
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = MyWidget()
w.show()
app.exec_()

Single QTreeWidgetItem instance on multiple QTreeWidget?

I'm trying to show a single QTreeWidgetItem instance on 2 QTreeWidgets, which ends up the item shown only on the 1st tree without being notified. I haven't seen its API doc talks about a limitation if any. Is there a way to workaround?
#!/usr/bin/python
import os
import sys
from PySide.QtCore import QFile
from PySide.QtUiTools import QUiLoader
from PySide.QtGui import QApplication, QTreeWidget, QTreeWidgetItem, QWidget
class MyTreeWidgetItem(QTreeWidgetItem):
def __init__(self, *args):
super(MyTreeWidgetItem, self).__init__()
class MyWidget(QWidget):
def __init__(self, *args):
super(MyWidget, self).__init__()
loader = QUiLoader()
file = QFile('./src/prove_qtreewidget/qtree_mainwidget.ui')
file.open(QFile.ReadOnly)
self.widget_ui = loader.load(file, self)
file.close()
item1 = MyTreeWidgetItem(self)
item1.setText(0, 'Item 1')
_tw1 = self.widget_ui.findChild(QTreeWidget, '_tree_widget_1')
_tw2 = self.widget_ui.findChild(QTreeWidget, '_tree_widget_2')
_tw1.addTopLevelItem(item1)
_tw2.addTopLevelItem(item1)
if __name__ == '__main__':
print("Running in " + os.getcwd() + " .\n")
app = QApplication(sys.argv)
win = MyWidget()
win.show()
app.exec_()
.ui file above is available here.
Using Qt 4.8, Ubuntu 12.04
I haven't tried PyQt binding but I just assume shouldn't be any different w/o proof.
What you need is a model and a QTreeView, that's for what they are for:
Model/View Programming: Widgets do not maintain internal data containers. They access external data through a standardized interface and therefore avoid data duplication.

catch link clicks in QtWebView and open in default browser

I am opening a page in QtWebView (in PyQt if that matters) and I want to open all links in the system default browser. I.e. a click on a link should not change the site in the QtWebView but it should open it with the default browser. I want to make it impossible to the user to change the site in the QtWebView.
How can I do that?
Thanks,
Albert
That does it:
import sys, webbrowser
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
app = QApplication(sys.argv)
web = QWebView()
web.load(QUrl("http://www.az2000.de/projects/javascript-project/"))
web.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
def linkClicked(url): webbrowser.open(str(url.toString()))
web.connect(web, SIGNAL("linkClicked (const QUrl&)"), linkClicked)
web.show()
sys.exit(app.exec_())
Updated example for PyQt5 (the magic is to re-implement the "acceptNavigationRequest" method):
from PyQt5 import QtWidgets, QtCore, QtGui, QtWebEngineWidgets
class RestrictedQWebEnginePage(QtWebEngineWidgets.QWebEnginePage):
""" Filters links so that users cannot just navigate to any page on the web,
but just to those pages, that are listed in allowed_pages.
This is achieved by re-implementing acceptNavigationRequest.
The latter could also be adapted to accept, e.g. URLs within a domain."""
def __init__(self, parent=None):
super().__init__(parent)
self.allowed_pages = []
def acceptNavigationRequest(self, qurl, navtype, mainframe):
# print("Navigation Request intercepted:", qurl)
if qurl in self.allowed_pages: # open in QWebEngineView
return True
else: # delegate link to default browser
QtGui.QDesktopServices.openUrl(qurl)
return False
class RestrictedWebViewWidget(QtWidgets.QWidget):
"""A QWebEngineView is required to display a QWebEnginePage."""
def __init__(self, parent=None, url=None, html_file=None):
super().__init__(parent)
self.view = QtWebEngineWidgets.QWebEngineView()
self.page = RestrictedQWebEnginePage()
if html_file:
print("Loading File:", html_file)
self.url = QtCore.QUrl.fromLocalFile(html_file)
self.page.allowed_pages.append(self.url)
self.page.load(self.url)
elif url:
print("Loading URL:", url)
self.url = QtCore.QUrl(url)
self.page.allowed_pages.append(self.url)
self.page.load(self.url)
# associate page with view
self.view.setPage(self.page)
# set layout
self.vl = QtWidgets.QVBoxLayout()
self.vl.addWidget(self.view)
self.setLayout(self.vl)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
web = RestrictedWebViewWidget(url="YOUR URL") # or YOUR local HTML file
web.show()
sys.exit(app.exec_())
When you click a link that has the target="_blank" attribute, QT calls the CreateWindow method in QWebEnginePage to create a new tab/new window.
The key is to re-implement this method to, instead of opening a new tab, open a new browser window.
class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
def createWindow(self, _type):
page = WebEnginePage(self)
page.urlChanged.connect(self.open_browser)
return page
def open_browser(self, url):
page = self.sender()
QDesktopServices.openUrl(url)
page.deleteLater()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.url = QUrl("https://stackoverflow.com/")
self.webView = QWebEngineView()
self.page = WebEnginePage(self.webView)
self.webView.setPage(self.page)
self.webView.load(self.url)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
web = MainWindow()
web.show()
sys.exit(app.exec_())

Resources