Putting buttons and Webview inside Tab Widget
-
I'm making a browser and I'm having trouble adding the tab functionality to it.
Every example I've seen places the tabs under the toolbar (with buttons and address bar), which is opposite to what modern browsers do.
How do I place the buttons and everything under the tabs, between webview and the tabs?
I tried to do this by placing a gridLayout inside the tab widget and then putting everything inside the layout, but this didn't work at all.This is basically where I'm at right now:
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import *class Browser(QWebEngineView):
#right click menu
def contextMenuEvent(self, event):
self.menus = QMenu()
self.menus.setStyleSheet("border-image:url(img/webbg2.png); QMenu::item::hover { text-color: rgb(30,30,30); }")
action1 = QAction("View source code", self)
self.menus.addAction(action1)
self.menus.popup(event.globalPos())class MainWindow(QMainWindow):
def init(self, *args, **kwargs):
super(MainWindow, self).init(*args, **kwargs)#resize window relative to screen size, prefers integers for some reason available_geometry = app.desktop().availableGeometry() self.resize(int(available_geometry.width() * 0.7), int(available_geometry.height() * 0.8)) #create tab widget self.tabs = QTabWidget() #making tabs as central widget self.setCentralWidget(self.tabs) self.newtab(QUrl('http://www.duckduckgo.com'), 'Tab') #GUI color scheme palette = QPalette() palette.setColor(QPalette.Window, QColor(179, 194, 217)) app.setPalette(palette) self.show() def newtab(self, qurl=None, label="Blank"): #if url is blank if qurl is None: qurl = QUrl('http://www.duckduckgo.com') #buttons #back self.backbutton = QPushButton(self.tabs) self.backbutton.setStyleSheet("QPushButton:!hover { border-image:url(img/back6054.png); min-width: 45px; min-height: 40px; }" "QPushButton:hover { border-image:url(img/back6054-h.png); }") #forward self.forwardbutton = QPushButton(self.tabs) self.forwardbutton.setStyleSheet("QPushButton:!hover { border-image:url(img/for6054.png); min-width: 45px; min-height: 40px; }" "QPushButton:hover { border-image:url(img/for6054-h.png); }") #creating Webview, which has been made into its own class self.browser = Browser() self.browser.setUrl(qurl) #setting tab index i = self.tabs.addTab(self.browser, label) self.tabs.setCurrentIndex(i)app = QApplication(sys.argv)
app.setApplicationName("Tabbed Browser")
window = MainWindow()
app.exec_() -
I'm making a browser and I'm having trouble adding the tab functionality to it.
Every example I've seen places the tabs under the toolbar (with buttons and address bar), which is opposite to what modern browsers do.
How do I place the buttons and everything under the tabs, between webview and the tabs?
I tried to do this by placing a gridLayout inside the tab widget and then putting everything inside the layout, but this didn't work at all.This is basically where I'm at right now:
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import *class Browser(QWebEngineView):
#right click menu
def contextMenuEvent(self, event):
self.menus = QMenu()
self.menus.setStyleSheet("border-image:url(img/webbg2.png); QMenu::item::hover { text-color: rgb(30,30,30); }")
action1 = QAction("View source code", self)
self.menus.addAction(action1)
self.menus.popup(event.globalPos())class MainWindow(QMainWindow):
def init(self, *args, **kwargs):
super(MainWindow, self).init(*args, **kwargs)#resize window relative to screen size, prefers integers for some reason available_geometry = app.desktop().availableGeometry() self.resize(int(available_geometry.width() * 0.7), int(available_geometry.height() * 0.8)) #create tab widget self.tabs = QTabWidget() #making tabs as central widget self.setCentralWidget(self.tabs) self.newtab(QUrl('http://www.duckduckgo.com'), 'Tab') #GUI color scheme palette = QPalette() palette.setColor(QPalette.Window, QColor(179, 194, 217)) app.setPalette(palette) self.show() def newtab(self, qurl=None, label="Blank"): #if url is blank if qurl is None: qurl = QUrl('http://www.duckduckgo.com') #buttons #back self.backbutton = QPushButton(self.tabs) self.backbutton.setStyleSheet("QPushButton:!hover { border-image:url(img/back6054.png); min-width: 45px; min-height: 40px; }" "QPushButton:hover { border-image:url(img/back6054-h.png); }") #forward self.forwardbutton = QPushButton(self.tabs) self.forwardbutton.setStyleSheet("QPushButton:!hover { border-image:url(img/for6054.png); min-width: 45px; min-height: 40px; }" "QPushButton:hover { border-image:url(img/for6054-h.png); }") #creating Webview, which has been made into its own class self.browser = Browser() self.browser.setUrl(qurl) #setting tab index i = self.tabs.addTab(self.browser, label) self.tabs.setCurrentIndex(i)app = QApplication(sys.argv)
app.setApplicationName("Tabbed Browser")
window = MainWindow()
app.exec_()@Harborman Demo:
import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtWebEngineWidgets import * class WebView(QWebEngineView): def contextMenuEvent(self, event): menus = QMenu() menus.setStyleSheet( "border-image:url(img/webbg2.png); QMenu::item::hover { text-color: rgb(30,30,30); }" ) action1 = QAction("View source code", self) menus.addAction(action1) menus.popup(event.globalPos()) class TabPage(QWidget): def __init__(self, parent=None): super().__init__(parent) self.backbutton = QPushButton() self.backbutton.setStyleSheet( "QPushButton:!hover { border-image:url(img/back6054.png); min-width: 45px; min-height: 40px; }" "QPushButton:hover { border-image:url(img/back6054-h.png); }" ) self.forwardbutton = QPushButton() self.forwardbutton.setStyleSheet( "QPushButton:!hover { border-image:url(img/for6054.png); min-width: 45px; min-height: 40px; }" "QPushButton:hover { border-image:url(img/for6054-h.png); }" ) self.webview = WebView() lay = QGridLayout(self) lay.addWidget(self.backbutton, 0, 0) lay.addWidget(self.forwardbutton, 0, 1) lay.addWidget(self.webview, 1, 0, 1, 2) class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) available_geometry = QGuiApplication.primaryScreen().availableGeometry() self.resize( int(available_geometry.width() * 0.7), int(available_geometry.height() * 0.8), ) self.tabs = QTabWidget() self.setCentralWidget(self.tabs) self.newtab(QUrl("http://www.duckduckgo.com"), "Tab") palette = QPalette() palette.setColor(QPalette.Window, QColor(179, 194, 217)) app.setPalette(palette) def newtab(self, qurl=None, label="Blank"): if qurl is None: qurl = QUrl("http://www.duckduckgo.com") page = TabPage() page.webview.load(qurl) i = self.tabs.addTab(page, label) self.tabs.setCurrentIndex(i) app = QApplication(sys.argv) app.setApplicationName("Tabbed Browser") window = MainWindow() window.show() app.exec_() -
@Harborman Demo:
import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtWebEngineWidgets import * class WebView(QWebEngineView): def contextMenuEvent(self, event): menus = QMenu() menus.setStyleSheet( "border-image:url(img/webbg2.png); QMenu::item::hover { text-color: rgb(30,30,30); }" ) action1 = QAction("View source code", self) menus.addAction(action1) menus.popup(event.globalPos()) class TabPage(QWidget): def __init__(self, parent=None): super().__init__(parent) self.backbutton = QPushButton() self.backbutton.setStyleSheet( "QPushButton:!hover { border-image:url(img/back6054.png); min-width: 45px; min-height: 40px; }" "QPushButton:hover { border-image:url(img/back6054-h.png); }" ) self.forwardbutton = QPushButton() self.forwardbutton.setStyleSheet( "QPushButton:!hover { border-image:url(img/for6054.png); min-width: 45px; min-height: 40px; }" "QPushButton:hover { border-image:url(img/for6054-h.png); }" ) self.webview = WebView() lay = QGridLayout(self) lay.addWidget(self.backbutton, 0, 0) lay.addWidget(self.forwardbutton, 0, 1) lay.addWidget(self.webview, 1, 0, 1, 2) class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) available_geometry = QGuiApplication.primaryScreen().availableGeometry() self.resize( int(available_geometry.width() * 0.7), int(available_geometry.height() * 0.8), ) self.tabs = QTabWidget() self.setCentralWidget(self.tabs) self.newtab(QUrl("http://www.duckduckgo.com"), "Tab") palette = QPalette() palette.setColor(QPalette.Window, QColor(179, 194, 217)) app.setPalette(palette) def newtab(self, qurl=None, label="Blank"): if qurl is None: qurl = QUrl("http://www.duckduckgo.com") page = TabPage() page.webview.load(qurl) i = self.tabs.addTab(page, label) self.tabs.setCurrentIndex(i) app = QApplication(sys.argv) app.setApplicationName("Tabbed Browser") window = MainWindow() window.show() app.exec_()@eyllanesc Thank you. I've been playing around with this demo. I noticed that things are a bit harder when the tabs are set up like that. For some reason I couldn't get "self.tabs.currentWidget.back()" type of methods to work in MainWindow class, so I replaced the currentWidget with just an instance of browser. It seemed to work but is probably a bad idea. Any idea why trying to call currentWidget gives a Nonetype error? Because of this I can't get tab titles to go to the current widget either.
Here's where I'm at:import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtWebEngineWidgets import * class Browser(QWebEngineView): def contextMenuEvent(self, event): self.menus = QMenu() action1 = QAction("Copy text", self) self.menus.addAction(action1) self.menus.popup(event.globalPos()) action1.triggered.connect(self.copytext) def copytext(self): self.triggerPageAction(QWebEnginePage.Copy) class Urlbar(QLineEdit): def contextMenuEvent(self, event): self.menus = QMenu() action1 = QAction("Copy", self) self.menus.addAction(action1) self.menus.popup(event.globalPos()) action1.triggered.connect(self.copytext) def copytext(self): self.copy() class Tabb(QTabWidget): def contextMenuEvent(self, event): self.menus = QMenu() class TabPage(QWidget): def __init__(self, MainWindow): super().__init__() self.MainWindow = MainWindow self.browser = Browser() self.layout = QGridLayout(self) self.layout.addWidget(self.browser, 1, 0, 1, 2) self.layout.setSpacing(0) #remove border around webview self.layout.setContentsMargins(QMargins()) toolbar = QToolBar() QToolBar.setContextMenuPolicy(self, Qt.NoContextMenu) toolbar.setIconSize(QSize(50, 44)) toolbar.setMovable(False) self.layout.addWidget(toolbar, 0, 0) #toolbar buttons and urlbar #back self.backbutton = QPushButton("go back") toolbar.addWidget(self.backbutton) #forward self.forwardbutton = QPushButton("go forward") toolbar.addWidget(self.forwardbutton) #refresh self.refreshbutton = QPushButton("refresh") toolbar.addWidget(self.refreshbutton) #address bar self.urlbar = Urlbar() font = QFont() font.setFamily("Arial") font.setPointSize(11) font.setBold(False) font.setWeight(50) self.urlbar.setFont(font) toolbar.addWidget(self.urlbar) self.urlbar.returnPressed.connect(self.urlhandler) def urlhandler(self): #when enter is pressed, sends the browser + url to MainWindow.go_to_url() browseri = self.browser url = QUrl.fromUserInput(self.urlbar.text()).toString() self.MainWindow.go_to_url(url, browseri) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setMinimumHeight(480) self.setMinimumWidth(600) self.tabs = Tabb() self.setCentralWidget(self.tabs) self.tabs.setTabsClosable(True) self.tabs.tabCloseRequested.connect(self.close_tab) self.tabs.setMovable(True) self.tabs.setDocumentMode(True) plusbutton = QPushButton("new tabb", self.tabs) plusbutton.clicked.connect(self.newtab) tabpage = TabPage(self) self.newtab() self.show() def newtab(self): index = self.tabs.count() url = QUrl("http://duckduckgo.com") page = TabPage(self) page.browser.load(url) browseri = page.browser page.backbutton.clicked.connect(lambda _:self.back(browseri)) page.forwardbutton.clicked.connect(lambda _:self.forward(browseri)) page.refreshbutton.clicked.connect(lambda _:self.refresh(browseri)) self.tabs.addTab(page, str(index)) self.tabs.setCurrentIndex(index) page.browser.loadFinished.connect(lambda tabtitle:self.on_load_finished(browseri)) def on_load_finished(self, browseri): print("test") title = browseri.page().title() #this thing doesn't work without currentWidget: i = self.tabs.indexOf(browseri) self.tabs.setTabText(i, title) def go_to_url(self, url, browseri): #you connect here from TabPage's self.urlbar browseri.load(QUrl(url)) def close_tab(self, index): if self.tabs.count() > 1: self.tabs.removeTab(index) return def back(self, browseri): #these don't work with self.tabs.currentWidget() for some reason! browseri.back() def forward(self, browseri): browseri.forward() def refresh(self, browseri): self.browser = browseri self.browser.reload() if __name__ == "__main__": app = QApplication(sys.argv) ex = MainWindow() sys.exit(app.exec_())