PyQt4 new modul - python

I want to do some things with the PyQt4 framework. So I decided to do some browser like thing. Here is the code. Its just simple:
import sys
from PyQt4 import QtGui, QtCore, QtWebKit
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.resize(250, 150)
self.setWindowTitle('Testbrowser')
exit = QtGui.QAction(QtGui.QIcon('icons/exit.png'), 'Exit', self)
exit.setShortcut('Ctrl+Q')
exit.setStatusTip('Exit application')
self.connect(exit, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
self.statusBar()
menubar = self.menuBar()
datei = menubar.addMenu('&Datei')
datei.addAction(exit)
tools = menubar.addMenu('&Tools')
app = QtGui.QApplication(sys.argv)
main = MainWindow()
web = QWebView()
web.load(QUrl("http://google.de"))
main.show()
sys.exit(app.exec_())
I think I understood some of the things here. But what I do not understand is, how can I work with new modules here? The MainWindow class inherits from the QtGui.QMainWindow class, thats ok. But what now? Should I create a whole new class which inherits from QWebView?? Kind of like :
class newclass(QWebView.QtWebKit):
def __init__(self):
QWebView.QtWebkit.__init__(self)
ect
Or how can I do this without a new class? Or how do I do this in general? I saw a webpage on which the author made a simple browser too. But he imported it in a new programm and made an object out of it and then did some stuff. Do I have to do this, or is there a simpler way? How is this all done in PyQt4?
Greets
some reference
http://pyqt.sourceforge.net/Docs/PyQt4/qwebview.html

Accessing elements of a module follows a dot notation convention in Python -- e.g. to access QWebView, you should use
web = QtWebkit.QWebView()
the URL would be
QtCore.QUrl("http://google.de")
If you want to have all of the names available to you without dot notation, you have to import everything:
from PyQt4.QtWebkit import *

Related

Avoid circular import when accessing instance value from main.py

I´m new to Python and programming in general. So maybe there is an easy solution for more experienced programmers.
I already read a lot of question regarding circular imports, but unfortunately there was nothing there that I can apply to my situation if I dont want to move all the code in one file.
I created an userinterface with pyqt (qt creator) and converted the mainwindow.ui to mainwindow.py.
My plan is to split the code into 3 modules. A main module to start the application, an ui module with the class of the main window and a buttons module with classes for the buttons.
My problem is that the functions within the button classes should change a label value of the main window instance. I learned to create the main window instance in the main module. As a result of this I need to import the instance from the main module into the buttons module to change the intended value and that leads to an circular import.
How do I have to organize/structure my code to avoid this?
Here is a short and simplified example for better understanding:
main.py
import sys
from qtpy import QtWidgets
from ui import MainWindow
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
ui.py
from qtpy import QtWidgets
from userinterface.mainwindow import Ui_MainWindow
import buttons
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.button_0 = buttons.NumberButton(0)
self.button_1 = buttons.NumberButton(1)
self.ui.btn_0.clicked.connect(self.button_0.button_clicked)
self.ui.btn_1.clicked.connect(self.button_1.button_clicked)
buttons.py
from main import window
class NumberButton:
def __init__(self, number):
self.number = str(number)
def button_clicked(self):
window.ui.lb_result.setText(self.number)
Your design problem is that your NumberButton class calls one specific window instance. Your have to let your buttons know to which window they belong. Try the following: remove the import statement from buttons.py and add a new parameter window to the __init__ method:
class NumberButton:
def __init__(self, window, number):
self.window = window
self.number = str(number)
def button_clicked(self):
self.window.ui.lb_result.setText(self.number)
Then instantiate in NumberButton like:
...
self.button_0 = buttons.NumberButton(self, 0)
...
If you only import the module python should automatically avoid circular imports. So do import ui and import buttons

How to load a Qt Designer file (.ui) in a QWizardPage using PySide2

I want to design my QWizardPages in Qt Designer and I want to load them into my Python program with PySide2. Previously I have been using PyQt5 without any problems but making the switch to PySide2 seems harder then expected.
The problem I am facing is that when I am adding a QWizardPage to my QWizard , the page is indeed added to the Wizard, but also an other (empty) page is added. I'm not able to find what I'm doing wrong so I was wondering if someone can have a look.
I have tried to add the pages with both the functions addPage() and setPage(), but they give the same results. What I also noticed is that when I explicitely set the Title of the page with setTitle(), the empty (unwanted) page gets this title, but not the page I designed in Qt Designer.
import os
import sys
from PySide2.QtWidgets import QWizard, QWizardPage, QApplication
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader
from enum import Enum
class MyWizard(QWizard):
def __init__(self):
super().__init__()
self.setPage(PageNumbers.page_one.value, PageOne(self))
class PageOne(QWizardPage):
def __init__(self, parent):
super().__init__(parent)
ui_file = os.path.join(__file__, '..', 'pageOne.ui')
file = QFile(ui_file)
file.open(QFile.ReadOnly)
loader = QUiLoader()
loader.load(file, parent)
file.close()
self.setTitle("This is another test Title")
class PageNumbers(Enum):
page_one = 1
if __name__ == '__main__':
app = QApplication(sys.argv)
wizard = MyWizard()
wizard.show()
app.exec_()
What I would expect is to have just one QWizardPage showing up with directly the Finish button. Instead I get two QWizardPages as shown in this image:
Can someone tell me what's going on?
(I get the expected result using PyQt5 with the following code: https://pastebin.com/6W2sx9M1)
The developers of PyQt implement functions to be able to create classes based on the .ui that is not implemented in Qt by default (Qt/C++ uses the MOC to do this work), but in the case of PySide2-Qt for python it does not implement it, only has the QUiLoader class that allows to create a widget based on the .ui unlike PyQt that allows filling a class.
In conclusion there is no equivalent in PySide2 of the loadUi function so you can not implement the same logic. PySide2 is not PyQt5, there are own equivalences since they use the same base but they have implementations, limitations and advantages.
Going to the practical problem, considering that the .ui is next to the .py the solution is the following:
import os
import sys
from PySide2 import QtCore, QtWidgets, QtUiTools
from enum import Enum
class PageNumbers(Enum):
page_one = 0
class MyWizard(QtWidgets.QWizard):
def __init__(self):
super().__init__()
ui_file = os.path.join(os.path.dirname(os.path.abspath(__file__)) ,'PageOne.ui')
page_one = create_widget(ui_file, self)
self.setPage(PageNumbers.page_one.value, page_one)
def create_widget(filename, parent=None):
file = QtCore.QFile(filename)
if not file.open(QtCore.QFile.ReadOnly):
return
loader = QtUiTools.QUiLoader()
widget = loader.load(file, parent)
return widget
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
wizard = MyWizard()
wizard.show()
sys.exit(app.exec_())

Detect Ctrl+S ion QTextedit?

So, I'm making a QTextEdit that edits a text file. I got the loading and saving working fine with buttons. But I got the habit of pressing Ctrl+S to save every time I paste something into the textedit because I used that in Notepad before. So I've been trying to implement it. But I can't wrap my head around how to detect and execute my save function. Lets call it savetext.
I've been going around trying to get keyPressEvent to work, but I just don't understand how it works. So I've been pretty helpless in trying to learn it.
My heavily simplified code looks like this:
class GUI(QProcess):
def init etc...
"Button creations and connect to save/load function"
self.textedit=QTextEdit()
def savetext(self):
code
def loadtext(self):
code
Now, how do I detect a key combination being detected in the QTextEdit, or anywhere in my program for that matter, and cause it to do savetext? In my case, Ctrl+S, though I'd just love a general explanation so I could apply it to any combo.
Use QShortcut and QKeySequence
from PyQt5.QtWidgets import QApplication, QTextEdit, QShortcut
from PyQt5.QtGui import QKeySequence
import sys
def slot():
print("Ctrl+S")
app = QApplication(sys.argv)
textedit=QTextEdit()
shortcut = QShortcut(QKeySequence("Ctrl+S"), textedit)
shortcut.activated.connect(slot)
textedit.show()
sys.exit(app.exec_())
You can probably use QShortcut, and right now it will activate only when textedit in focus. If you want to change the behavior please take a look here
Here is a example
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
layout = QtGui.QVBoxLayout(self)
self.edit = QtGui.QTextEdit()
layout.addWidget(self.edit)
self.button = QtGui.QPushButton('Test')
layout.addWidget(self.button)
foo = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+S"), self.edit, self.saveCall, context=QtCore.Qt.WidgetShortcut)
def saveCall(self):
self.edit.append('Please save me')
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

How do I open sub window after I click on button on main screen in PyQt4

HI I am trying to make a simple converter.
I have used PyQt4 designed to make the Gui
I want to know how launch a new window after I click on the individual button.
This is the interface I have created using PyQt4 Designer.
Here is the Image link :
and I want to launch this windows when I click on currency button.
Here is the Image Link:
Here is my code for main.py
from PyQt4 import QtGui
from main_screen import mainscreen
def main():
import sys
qApp = QtGui.QApplication(sys.argv)
aw = mainscreen()
aw.show()
sys.exit(qApp.exec_())
if __name__ == '__main__':
main()
and code for mainscreen.py
from PyQt4 import QtCore, QtGui
from window_main import Ui_MainWindow
class mainscreen(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(mainscreen,self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
How can I open new window after I click on currency button (object name for currency button is "currency_bt")
and do I have to write the code for currency in same window or I have to write in new window.
How do I do it.
I am new to Python Gui programming.
Each GUI form that you create in Qt Designer needs to be converted into a python module using pyuic. So, to start with, you need to do the same for currency.ui that you did for window_main.
Now you can import your currency window class into mainscreen.py, and connect a button to handler so you can display it.
The code would look something like this:
from PyQt4 import QtCore, QtGui
from window_main import Ui_MainWindow
from currency import Ui_CurrencyWindow
class CurrencyWindow(QtGui.QMainWindow, Ui_CurrencyWindow):
def __init__(self, parent=None):
super(CurrencyWindow, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setupUi(self)
class MainScreen(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainScreen, self).__init__(parent)
self.setupUi(self)
self.currencyButton.clicked.connect(self.handleCurrencyButton)
def handleCurrencyButton(self):
window = CurrencyWindow(self)
window.show()
After looking at this example code, it will probably occur to you that you are going to end up importing a lot of modules, and have a lot of boiler-plate code to write for each one of them (which is not much fun).
So I would advise you to consider changing your GUI design, so that you have one main window containing a tabwidget, and then have a separate tab for each of your converters. This will not only make your application much easier to write, but it should also make it a lot nicer to use.
I'm making my bachelor thesis in PyQt4. First I also wanted to use the designer (generating code is nice), but afterall I was not using it during my work. Maybe it's a matter of taste.
But for your question (I did this without the QtDesigner):
Let's say we have a main window class:
import sys
from PyQt4 import QtCore, QtGui
class mainscreen(QtGui.QMainWindow):
def __init__(self, parent=None):
super(mainscreen,self).__init__(parent)
self.button = QtGui.QPushButton("push")
self.button.clicked.connect(self.pushed)
#pyqtSlot()
def pushed(self):
# in this section here you can create the new window and show it
qApp = QtGui.QApplication(sys.argv)
aw = mainscreen()
aw.show()
sys.exit(qApp.exec_())
There are some good tutorials (http://zetcode.com/gui/pyqt4/ helped me getting started).
Make two programs: main_win.py and second_win.py, then in main_win.py put this lines:
from os import system as sh //In the begin
def openewin(self): //In the class main_win
sh("python second_win.py")
Ready, just connect the push button to function openewin!

Accessing QTextHtmlImporter in PyQt4

I'm writing a cross platform app in PyQt4. For a particular feature, I would like to access the QTextHtmlImporter class of Qt4. There is no direct python adapter class available in PyQt4. The class is part of the src/gui/text/qtextdocumentfragment_p.h file. Is there any way I can access that in Python?
I would like to modify QTextDocument.setHtml(), which code is:
void QTextDocument::setHtml(const QString &html) {
Q_D(QTextDocument); setUndoRedoEnabled(false);
d->clear();
QTextHtmlImporter(this, html).import();
setUndoRedoEnabled(true);
}
to
void QTextDocument::setHtml(const QString &html) {
Q_D(QTextDocument);
QTextHtmlImporter(this, html).import();
}
Basically setting the HTML without clearing the history. I planned to do this by using a derived class of PyQt4's QTextDocument overriding the setHtml function. Is there any other way to do this?
QTextHtmlImporter isn't even part of the Qt4 API, so the short answer is: no, there's no way to access it in PyQt4.
You could, of course, attempt to port the code to PyQt4, but I'm guessing that would be a non-trivial task.
The question is: why do you think you need to do this?
Why can't you use QTextCursor.insertHtml or QTextDocumentFragment.fromHtml?
EDIT
Here's an example of how to set the html in a text document without clearing the undo history:
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
layout = QtGui.QVBoxLayout(self)
self.edit = QtGui.QTextEdit(self)
self.undo = QtGui.QPushButton('Undo')
self.redo = QtGui.QPushButton('Redo')
self.insert = QtGui.QPushButton('Set Html')
layout.addWidget(self.edit)
layout.addWidget(self.undo)
layout.addWidget(self.redo)
layout.addWidget(self.insert)
self.undo.clicked.connect(self.edit.undo)
self.redo.clicked.connect(self.edit.redo)
self.insert.clicked.connect(self.handleInsert)
self.edit.append('One')
self.edit.append('Two')
self.edit.append('Three')
def handleInsert(self):
cursor = QtGui.QTextCursor(self.edit.document())
cursor.select(QtGui.QTextCursor.Document)
cursor.insertHtml("""<p>Some <b>HTML</b> text</p>""")
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

Categories

Resources