from PyQt5 import Qt
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import *
from sys import argv
class Window(QMainWindow):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.browser = QWebEngineView()
self.browser.setUrl(QUrl('https://www.duckduckgo.com'))
self.browser.urlChanged.connect(self.update_AddressBar)
self.setCentralWidget(self.browser)
self.navigation_bar = QToolBar('Navigation Toolbar')
self.addToolBar(self.navigation_bar)
self.navigation_bar.setAttribute(Qt.Qt.WA_StyledBackground, True)
self.navigation_bar.setStyleSheet('background-color: white;')
self.navigation_bar.setMinimumSize(0, 75)
self.navigation_bar.setMovable(False)
back_button = QAction("←", self)
back_button.setStatusTip('Go to previous page you visited')
back_button.triggered.connect(self.browser.back)
self.navigation_bar.addAction(back_button)
next_button = QAction("→", self)
next_button.setStatusTip('Go to next page')
next_button.triggered.connect(self.browser.forward)
self.navigation_bar.addAction(next_button)
refresh_button = QAction("⟳", self)
refresh_button.setStatusTip('Refresh this page')
refresh_button.triggered.connect(self.browser.reload)
self.navigation_bar.addAction(refresh_button)
home_button = QAction("⌂", self)
home_button.setStatusTip('Go to home page (Google page)')
home_button.triggered.connect(self.go_to_home)
self.navigation_bar.addAction(home_button)
#self.navigation_bar.addSeparator()
self.URLBar = QLineEdit()
self.URLBar.returnPressed.connect(lambda: self.go_to_URL(QUrl(self.URLBar.text()))) # This specifies what to do when enter is pressed in the Entry field
self.navigation_bar.addWidget(self.URLBar)
self.addToolBarBreak()
self.show()
def go_to_home(self):
self.browser.setUrl(QUrl('https://www.duckduckgo.com/'))
def go_to_URL(self, url: QUrl):
if url.scheme() == '':
url.setScheme('http://')
self.browser.setUrl(url)
self.update_AddressBar(url)
def update_AddressBar(self, url):
self.URLBar.setText(url.toString())
self.URLBar.setCursorPosition(0)
app = QApplication(argv)
app.setApplicationName('Libertatem Browser')
window = Window()
app.exec_()
As you can see in my code, I have 4 QActions. I want to make these bigger. How can I do that? I have seen others using back_button.geometry(), but you can't do that with QActions.
I would prefer to keep them as QActions, because it took me a long while to set them up. As a side note, would changing the font size make the button bigger?
If you change the size of the button associated with the QAction it would not make a big difference, you could do it in the following way:
button = toolbar.widgetForAction(action)
button.setFixedSize(100, 100)
But in this case it is better to change the font size since the size of the button (and the height of the QToolBar) depends on it.
import sys
from PyQt5.QtCore import Qt, QUrl, QSize
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QAction, QApplication, QLineEdit, QMainWindow, QToolBar
from PyQt5.QtWebEngineWidgets import QWebEngineView
class Window(QMainWindow):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.browser = QWebEngineView()
self.browser.setUrl(QUrl("https://www.duckduckgo.com"))
self.browser.urlChanged.connect(self.update_AddressBar)
self.setCentralWidget(self.browser)
self.navigation_bar = QToolBar("Navigation Toolbar", movable=False)
self.addToolBar(self.navigation_bar)
self.navigation_bar.setAttribute(Qt.WA_StyledBackground, True)
self.navigation_bar.setStyleSheet("background-color: white;")
font = QFont()
font.setPixelSize(40)
back_action = QAction("←", self)
back_action.setStatusTip("Go to previous page you visited")
back_action.triggered.connect(self.browser.back)
back_action.setFont(font)
self.navigation_bar.addAction(back_action)
next_action = QAction("→", self)
next_action.setStatusTip("Go to next page")
next_action.triggered.connect(self.browser.forward)
next_action.setFont(font)
self.navigation_bar.addAction(next_action)
refresh_action = QAction("⟳", self)
refresh_action.setStatusTip("Refresh this page")
refresh_action.triggered.connect(self.browser.reload)
refresh_action.setFont(font)
self.navigation_bar.addAction(refresh_action)
home_action = QAction("⌂", self)
home_action.setStatusTip("Go to home page (Google page)")
home_action.setFont(font)
home_action.triggered.connect(self.go_to_home)
self.navigation_bar.addAction(home_action)
self.URLBar = QLineEdit()
self.URLBar.returnPressed.connect(self.handle_return_pressed)
self.navigation_bar.addWidget(self.URLBar)
def go_to_home(self):
self.browser.setUrl(QUrl("https://www.duckduckgo.com/"))
def go_to_URL(self, url: QUrl):
if url.scheme() == "":
url.setScheme("http://")
self.browser.setUrl(url)
self.update_AddressBar(url)
def update_AddressBar(self, url):
self.URLBar.setText(url.toString())
self.URLBar.setCursorPosition(0)
def handle_return_pressed(self):
url = QUrl.fromUserInput(self.URLBar.text())
self.go_to_URL(url)
def main():
app = QApplication(sys.argv)
app.setApplicationName("Libertatem Browser")
window = Window()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Related
I'm making a custom browser, following a tutorial: https://www.youtube.com/watch?v=z-5bZ8EoKu4
I have coded everything to the T, and for some reason when I open the browser, even though I have self.browser.setUrl(QUrl('http://duckduckgo.com')) set for the default url to open to. How can I fix this?
The code:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.browser = QWebEngineView()
self.browser.setUrl(QUrl('http://duckduckgo.com'))
self.setCentralWidget(self.browser)
self.showMaximized()
# navbar
navbar = QToolBar()
self.addToolBar(navbar)
back_btn = QAction('Back', self)
back_btn.triggered.connect(self.browser.back)
navbar.addAction(back_btn)
forward_btn = QAction('Forward', self)
forward_btn.triggered.connect(self.browser.forward)
navbar.addAction(forward_btn)
reload_btn = QAction('Reload', self)
reload_btn.triggered.connect(self.browser.reload)
navbar.addAction(reload_btn)
home_btn = QAction('home', self)
home_btn.triggered.connect(self.navigate_home)
navbar.addAction(home_btn)
self.url_bar = QLineEdit()
self.url_bar.returnPressed.connect(self.navigate_to_url)
navbar.addWidget(self.url_bar)
def navigate_home(self):
self.browser.setUrl(QUrl('http://duckduckgo.com'))
def navigate_to_url(self):
url = self.url_bar.text()
self.browser.setUrl(QUrl(url))
app = QApplication(sys.argv)
QApplication.setApplicationName('quicksearch')
window = MainWindow()
app.exec_()"
I would like when I click on a buttom from a toolbar created with PyQt get the selected items in a QListWidget created in other class (LisWorkDirectory class).
In the ToolBar.py in the compilation_ function, I would like to get all selected items. I want to get the instance of the ListWorkDirectory class to get the QListWidget that I created the first time I have launched my app.
If I instanciate ListWorkDirectory, I get a new instance, and the selectedItems return a empty list, it is a normal behaviour.
Maybe my architecture is not correct, so if you have any suggestion or remarks don't' hesitate to learn me.
Below my code so that you understand my request :
main.py
from MainWindow import MainWindow
from MenuBar import MenuBar
from ToolBar import ToolBar
from PyQt5.QtWidgets import QApplication
import sys
app = QApplication(sys.argv)
#Window
windowApp = MainWindow("pyCompile")
#MenuBar
menuBar = MenuBar()
#ToolBar
toolBar = ToolBar()
windowApp.setMenuBar(menuBar)
windowApp.addToolBar(toolBar)
windowApp.show()
sys.exit(app.exec_())
MainWindow.py
from PyQt5.QtWidgets import QMainWindow, QWidget, QLineEdit, QPushButton, QListWidget,QListWidgetItem,QPlainTextEdit, QFileDialog, QStatusBar ,QVBoxLayout, QHBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
from ListWorkDirectory import ListWorkDirectory
from Logger import MyDialog
import logging
import os
class MainWindow(QMainWindow):
def __init__(self, windowTitle):
super().__init__()
#Logger
self.logger = MyDialog()
logging.info("pyCompile version 0.1")
self.setGeometry(150,250,600,350)
self.setWindowTitle(windowTitle)
self.workDirectoryField = QLineEdit()
self.workDirectoryField.setPlaceholderText("Select your work directory ...")
self.workDirectoryField.setText("F:/WORKSPACE/Projects")
self.workDirectoryButton = QPushButton()
self.workDirectoryButton.setIcon(QIcon(":folder.svg"))
self.workDirectoryButton.clicked.connect(self.launchDialog)
self.hBoxLayout = QHBoxLayout()
self.hBoxLayout.addWidget(self.workDirectoryField)
self.hBoxLayout.addWidget(self.workDirectoryButton)
#List folder in work directory
self.myListFolder = ListWorkDirectory()
print(self.myListFolder)
self.workDirectoryField.textChanged[str].connect(self.myListFolder.update)
self.hBoxLayoutLogger = QHBoxLayout()
self.hBoxLayoutLogger.addWidget(self.myListFolder)
self.hBoxLayoutLogger2 = QHBoxLayout()
self.hBoxLayoutLogger2.addWidget(self.logger)
self.centralWidget = QWidget(self)
self.setCentralWidget(self.centralWidget)
self.vBoxLayout = QVBoxLayout(self.centralWidget)
self.vBoxLayout.addLayout(self.hBoxLayout)
self.vBoxLayout.addLayout(self.hBoxLayoutLogger)
self.vBoxLayout.addLayout(self.hBoxLayoutLogger2)
#Status Bar
self.statusBar = QStatusBar()
self.statusBar.showMessage("Welcome in pyCompile", 5000)
self.setStatusBar(self.statusBar)
def launchDialog(self):
workDirectory = QFileDialog.getExistingDirectory(self, caption="Select work directory")
print(workDirectory)
self.workDirectoryField.setText(workDirectory)
MenuBar.py
from PyQt5.QtWidgets import QMenuBar
class MenuBar(QMenuBar):
def __init__(self):
super().__init__()
self.fileMenu = "&File"
self.editMenu = "&Edit"
self.helpMenu = "&Help"
self.initUI()
def initUI(self):
self.addMenu(self.fileMenu)
self.addMenu(self.editMenu)
self.addMenu(self.helpMenu)
ToolBar.py
from PyQt5.QtWidgets import QMainWindow, QToolBar, QAction
from PyQt5.QtGui import QIcon
import qrc_resources
from ListWorkDirectory import ListWorkDirectory
class ToolBar(QToolBar, ListWorkDirectory):
def __init__(self):
super().__init__()
self._createActions()
self.initUI()
def initUI(self):
self.setMovable(False)
self.addAction(self.compileAction)
self.addAction(self.settingsAction)
self.addAction(self.quitAction)
def _createActions(self):
self.compileAction = QAction(self)
self.compileAction.setStatusTip("Launch compilation")
self.compileAction.setText("&Compile")
self.compileAction.setIcon(QIcon(":compile.svg"))
self.compileAction.triggered.connect(self.compilation_)
self.settingsAction = QAction(self)
self.settingsAction.setText("&Settings")
self.settingsAction.setIcon(QIcon(":settings.svg"))
self.quitAction = QAction(self)
self.quitAction.setText("&Quit")
self.quitAction.setIcon(QIcon(":quit.svg"))
def compilation_(self):
"""
Get the instance of ListWorkDirectory to get selected items and launch the
compilation
"""
ListWorkDirectory.py
from PyQt5.QtWidgets import QListWidget,QListWidgetItem
from PyQt5.QtCore import Qt, QDir
import os
class ListWorkDirectory(QListWidget):
def __init__(self):
super().__init__()
self.clear()
def update(self, workDirectoryField):
isPathCorrect = self.checkPath(workDirectoryField)
if(isPathCorrect):
listOfDirectory = self.getFolderList(workDirectoryField, os.listdir(workDirectoryField))
for folder in listOfDirectory:
self.item = QListWidgetItem(folder)
self.item.setCheckState(Qt.Unchecked)
self.addItem(self.item)
else:
self.clear()
def checkPath(self, path):
QPath = QDir(path)
isQPathExist = QPath.exists()
isPathEmpty = self.isPathEmpty(path)
if(isQPathExist and not isPathEmpty):
return True
else:
return False
def getFolderList(self, path, listOfFiles):
listOfFolders=[]
for file_ in listOfFiles:
if(os.path.isdir(os.path.join(path, file_))):
listOfFolders.append(file_)
else:
pass
return listOfFolders
def isPathEmpty(self, path):
if(path != ""):
return False
else:
return True
Thank you for your help.
When you add widget to window (or to other widget) then this window (or widget) is its parent and you can use self.parent() to access element in window (or widget). When widgets are nested then you may even use self.parent().parent()
def compilation_(self):
"""
Get the instance of ListWorkDirectory to get selected items and launch the
compilation
"""
print(self.parent().myListFolder)
EDIT:
Class ListWorkDirectory has function item(number) to get item from list - but you overwrite it with line self.item = QListWidgetItem(folder). If you remove self. and use
item = QListWidgetItem(folder)
item.setCheckState(Qt.Unchecked)
self.addItem(item)
then this will show only checked items
def compilation_(self):
"""
Get the instance of ListWorkDirectory to get selected items and launch the
compilation
"""
lst = self.parent().myListFolder
for x in range(lst.count()):
item = lst.item(x)
#print(item.checkState(), item.text())
if item.checkState() :
print(item.text())
Full working code - everyone can simply copy all to one file and run it.
from PyQt5.QtWidgets import QMainWindow, QWidget, QLineEdit, QPushButton, QListWidget,QListWidgetItem,QPlainTextEdit, QFileDialog, QStatusBar ,QVBoxLayout, QHBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
import logging
import os
# ---
from PyQt5.QtWidgets import QMenuBar
class MenuBar(QMenuBar):
def __init__(self):
super().__init__()
self.fileMenu = "&File"
self.editMenu = "&Edit"
self.helpMenu = "&Help"
self.initUI()
def initUI(self):
self.addMenu(self.fileMenu)
self.addMenu(self.editMenu)
self.addMenu(self.helpMenu)
# ---
from PyQt5.QtWidgets import QMainWindow, QToolBar, QAction
from PyQt5.QtGui import QIcon
class ToolBar(QToolBar):
def __init__(self):
super().__init__()
self._createActions()
self.initUI()
def initUI(self):
self.setMovable(False)
self.addAction(self.compileAction)
self.addAction(self.settingsAction)
self.addAction(self.quitAction)
def _createActions(self):
self.compileAction = QAction(self)
self.compileAction.setStatusTip("Launch compilation")
self.compileAction.setText("&Compile")
self.compileAction.setIcon(QIcon(":compile.svg"))
self.compileAction.triggered.connect(self.compilation_)
self.settingsAction = QAction(self)
self.settingsAction.setText("&Settings")
self.settingsAction.setIcon(QIcon(":settings.svg"))
self.quitAction = QAction(self)
self.quitAction.setText("&Quit")
self.quitAction.setIcon(QIcon(":quit.svg"))
def compilation_(self):
"""
Get the instance of ListWorkDirectory to get selected items and launch the
compilation
"""
lst = self.parent().myListFolder
for x in range(lst.count()):
item = lst.item(x)
#print(item.checkState(), item.text())
if item.checkState() :
print(item.text())
# ---
from PyQt5.QtWidgets import QListWidget, QListWidgetItem
from PyQt5.QtCore import Qt, QDir
import os
class ListWorkDirectory(QListWidget):
def __init__(self):
super().__init__()
self.clear()
def update(self, workDirectoryField):
isPathCorrect = self.checkPath(workDirectoryField)
if(isPathCorrect):
listOfDirectory = self.getFolderList(workDirectoryField, os.listdir(workDirectoryField))
for folder in listOfDirectory:
item = QListWidgetItem(folder)
item.setCheckState(Qt.Unchecked)
self.addItem(item)
else:
self.clear()
def checkPath(self, path):
QPath = QDir(path)
isQPathExist = QPath.exists()
isPathEmpty = self.isPathEmpty(path)
if(isQPathExist and not isPathEmpty):
return True
else:
return False
def getFolderList(self, path, listOfFiles):
listOfFolders=[]
for file_ in listOfFiles:
if(os.path.isdir(os.path.join(path, file_))):
listOfFolders.append(file_)
else:
pass
return listOfFolders
def isPathEmpty(self, path):
if(path != ""):
return False
else:
return True
class MainWindow(QMainWindow):
def __init__(self, windowTitle):
super().__init__()
#Logger
#self.logger = MyDialog()
logging.info("pyCompile version 0.1")
self.setGeometry(150,250,600,350)
self.setWindowTitle(windowTitle)
self.workDirectoryField = QLineEdit()
self.workDirectoryField.setPlaceholderText("Select your work directory ...")
self.workDirectoryField.setText("F:/WORKSPACE/Projects")
self.workDirectoryButton = QPushButton()
self.workDirectoryButton.setIcon(QIcon(":folder.svg"))
self.workDirectoryButton.clicked.connect(self.launchDialog)
self.hBoxLayout = QHBoxLayout()
self.hBoxLayout.addWidget(self.workDirectoryField)
self.hBoxLayout.addWidget(self.workDirectoryButton)
#List folder in work directory
self.myListFolder = ListWorkDirectory()
print(self.myListFolder)
self.workDirectoryField.textChanged[str].connect(self.myListFolder.update)
self.hBoxLayoutLogger = QHBoxLayout()
self.hBoxLayoutLogger.addWidget(self.myListFolder)
self.hBoxLayoutLogger2 = QHBoxLayout()
#self.hBoxLayoutLogger2.addWidget(self.logger)
self.centralWidget = QWidget(self)
self.setCentralWidget(self.centralWidget)
self.vBoxLayout = QVBoxLayout(self.centralWidget)
self.vBoxLayout.addLayout(self.hBoxLayout)
self.vBoxLayout.addLayout(self.hBoxLayoutLogger)
self.vBoxLayout.addLayout(self.hBoxLayoutLogger2)
#Status Bar
self.statusBar = QStatusBar()
self.statusBar.showMessage("Welcome in pyCompile", 5000)
self.setStatusBar(self.statusBar)
def launchDialog(self):
workDirectory = QFileDialog.getExistingDirectory(self, caption="Select work directory")
print(workDirectory)
self.workDirectoryField.setText(workDirectory)
# ---
from PyQt5.QtWidgets import QApplication
import sys
app = QApplication(sys.argv)
#Window
windowApp = MainWindow("pyCompile")
#MenuBar
menuBar = MenuBar()
#ToolBar
toolBar = ToolBar()
windowApp.setMenuBar(menuBar)
windowApp.addToolBar(toolBar)
windowApp.show()
sys.exit(app.exec_())
I'm trying to write a Python program using PyQt5 that will display a window in each iteration of the for loop. I would like to close after incrementing and displaying the next window. However, I do not know how to stop the loop every iteration and at the moment I am getting 6 windows at once.
main.py
import sys
from PyQt5.QtWidgets import (QLineEdit, QVBoxLayout, QMainWindow,
QWidget, QDesktopWidget, QApplication, QPushButton, QLabel,
QComboBox, QFileDialog, QRadioButton)
from PyQt5.QtCore import pyqtSlot, QByteArray
from alert import Window2
from test import test
class SG(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(300, 150)
self.setWindowTitle('TEST')
self.resultsGen = QPushButton('TEST', self)
self.resultsGen.clicked.connect(lambda: self.on_click())
self.show()
#pyqtSlot()
def on_click(self):
test(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
sg = SG()
sys.exit(app.exec_())
alert.py
from PyQt5.QtWidgets import (QLineEdit, QVBoxLayout, QMainWindow,
QWidget, QDesktopWidget, QApplication, QPushButton, QLabel,
QComboBox, QFileDialog, QRadioButton)
from PyQt5.QtCore import pyqtSlot, QByteArray
from PyQt5.QtGui import QPixmap
from PyQt5 import QtGui, QtCore
class Window2(QMainWindow):
def __init__(self):
super().__init__()
self.initPopup()
def initPopup(self):
self.resize(500, 500)
self.setWindowTitle("Window22222")
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
lay = QVBoxLayout(self.central_widget)
label = QLabel(self)
pixmap = QPixmap('cropped/8.png')
label.setPixmap(pixmap)
self.resize(pixmap.width(), pixmap.height())
lay.addWidget(label)
self.textbox = QLineEdit(self)
self.textbox.move(20, 20)
self.textbox.resize(280, 40)
# Create a button in the window
self.button = QPushButton('Show text', self)
self.button.move(20, 80)
# connect button to function on_click
self.button.clicked.connect(lambda: self.on_clickX())
self.show()
#pyqtSlot()
def on_clickX(self):
textboxValue = self.textbox.text()
print(textboxValue)
self.textbox.setText("")
self.hide()
test.py
from alert import Window2
def test(self):
for x in range(6):
w = Window2()
As soon as you run the for cycle, all the code of the initialization will be executed, which includes the show() call you used at the end of initPopup().
A simple solution is to create a new signal that is emitted whenever you hide a window, and connect that signal to a function that creates a new one until it reaches the maximum number.
main.py:
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
from alert import Window2
class SG(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.alerts = []
def initUI(self):
self.resize(300, 150)
self.setWindowTitle('TEST')
self.resultsGen = QPushButton('TEST', self)
self.resultsGen.clicked.connect(self.nextAlert)
self.show()
def nextAlert(self):
if len(self.alerts) >= 6:
return
alert = Window2()
self.alerts.append(alert)
alert.setWindowTitle('Window {}'.format(len(self.alerts)))
alert.closed.connect(self.nextAlert)
alert.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
sg = SG()
sys.exit(app.exec_())
alert.py:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Window2(QMainWindow):
closed = pyqtSignal()
def __init__(self):
super().__init__()
self.initPopup()
def initPopup(self):
self.resize(500, 500)
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
lay = QVBoxLayout(self.central_widget)
label = QLabel(self)
pixmap = QPixmap('cropped/8.png')
label.setPixmap(pixmap)
self.resize(pixmap.width(), pixmap.height())
lay.addWidget(label)
self.textbox = QLineEdit(self)
lay.addWidget(self.textbox)
# Create a button in the window
self.button = QPushButton('Show text', self)
lay.addWidget(self.button)
# connect button to function on_click
self.button.clicked.connect(lambda: self.on_clickX())
self.show()
#pyqtSlot()
def on_clickX(self):
textboxValue = self.textbox.text()
print(textboxValue)
self.textbox.setText("")
self.hide()
self.closed.emit()
Just note that with this very simplified example the user might click on the button of the "SG" widget even if an "alert" window is visibile. You might prefer to use a QDialog instead of a QMainWindow and make the main widget a parent of that dialog.
main.py:
class SG(QWidget):
# ...
def nextAlert(self):
if len(self.alerts) >= 6:
return
alert = Window2(self)
# ...
alert.py:
class Window2(QDialog):
closed = pyqtSignal()
def __init__(self, parent):
super().__init__()
self.initPopup()
def initPopup(self):
self.resize(500, 500)
# a QDialog doesn't need a central widget
lay = QVBoxLayout(self)
# ...
Also, if an alert window is closed using the "X" button the new one will not be shown automatically. To avoid that, you can implement the "closeEvent" and ignore the event, so that the user will not be able to close the window until the button is clicked. As QDialogs can close themself when pressing the escape key, I'm also ignoring that situation.
alert.py:
class Window2(QMainWindow):
# ...
def closeEvent(self, event):
event.ignore()
def keyPressEvent(self, event):
if event.key() != Qt.Key_Escape:
super().keyPressEvent(event)
I have two files, one for my main window, which has one image and one button and one for a new window. What I want it to do is that when I push the button from my main window, it lets me load a file and show it in a TextEdit widget in the new window
so here I have the files I'm using:
MainWindow.py
import sys
import os
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtWidgets import QPushButton, QVBoxLayout, QTextEdit, QHBoxLayout, QLabel, QMainWindow, QAction, QFileDialog
class Window(QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.img = QLabel()
self.relleno=QLabel()
self.btn_load = QPushButton('Load')
self.width = 400
self.height = 150
self.init_ui()
def init_ui(self):
self.img.setPixmap(QtGui.QPixmap("someimage.png"))
h_layout = QHBoxLayout()
v_layout = QVBoxLayout()
h_final = QHBoxLayout()
h_layout.addWidget(self.img)
v_layout.addWidget(self.btn_load)
h_final.addLayout(h_layout)
h_final.addLayout(v_layout)
self.btn_load.clicked.connect(self.loadafile)
self.setLayout(h_final)
self.setWindowTitle('This is main window')
self.setGeometry(600,150,self.width,self.height)
self.show()
def loadafile(self):
filename = QFileDialog.getOpenFileName(self, 'Open File', os.getenv('HOME'))
with open(filename[0], 'r') as f:
file_text = f.read()
return file_text
def main():
app = QApplication(sys.argv)
main = Window()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
NewWindow.py
import os
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTextEdit, QVBoxLayout
from MainWindow import loadafile
info=loadafile()
class SecondWindow(QWidget):
def __init__(self):
super(SecondWindow, self).__init__()
self.text = QTextEdit(self)
self.init_ui()
def init_ui(self):
v_layout = QVBoxLayout()
v_layout.addWidget(self.text)
self.setLayout(v_layout)
self.setText(info)
self.setWindowTitle('Opened Text')
self.show()
app = QApplication(sys.argv)
shower = SecondWindow()
sys.exit(app.exec_())
I think the loadafile does return my file_text variable but I don't know how to open the new window from there. I think I need to use a destructor for main window and then show the new window but I'm not sure of how to do this (This is the first time I try OOP)
A program is not a set of files, especially in OOP a program is the interactions of objects. And the objects interact if they have the same scope, so both windows must be created in one place so that the information from one pass to the other.
On the other hand in Qt there is a fundamental concept that is the signals, this functionality allows to notify the change of a state to another object without a lot of dependency, so in this case I will create a signal that transmits the text to the other object.
NewWindow.py
from PyQt5 import QtWidgets
class SecondWindow(QtWidgets.QWidget):
def __init__(self):
super(SecondWindow, self).__init__()
self.text = QtWidgets.QTextEdit(self)
self.init_ui()
def init_ui(self):
v_layout = QtWidgets.QVBoxLayout(self)
v_layout.addWidget(self.text)
self.setWindowTitle('Opened Text')
self.show()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
shower = SecondWindow()
sys.exit(app.exec_())
MainWindow.py
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from NewWindow import SecondWindow
class Window(QtWidgets.QWidget):
textChanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.img =QtWidgets.QLabel()
self.relleno=QtWidgets.QLabel()
self.btn_load = QtWidgets.QPushButton('Load')
self.width = 400
self.height = 150
self.init_ui()
def init_ui(self):
self.img.setPixmap(QtGui.QPixmap("someimage.png"))
h_final = QtWidgets.QHBoxLayout(self)
h_final.addWidget(self.img)
h_final.addWidget(self.btn_load)
self.btn_load.clicked.connect(self.loadafile)
self.setWindowTitle('This is main window')
self.setGeometry(600,150,self.width,self.height)
self.show()
#QtCore.pyqtSlot()
def loadafile(self):
filename, _ = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', os.getenv('HOME'))
with open(filename, 'r') as f:
file_text = f.read()
self.textChanged.emit(file_text)
def main():
app = QtWidgets.QApplication(sys.argv)
main = Window()
s = SecondWindow()
main.textChanged.connect(s.text.append)
sys.exit(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.