How to include folium map into PyQt5 application window? - python

I would like to ask how do I go about including a folium map into PyQt 5 window application such that the map does not take up the whole window. I have found a similar post on StackOverflow "How to show Folium map inside a PyQt5 GUI?", however, the solution code provided shown the folium map takes up the whole of the PyQt 5 window application.
So my question is how do I include the folium map but only takes up a portion of the PyQt 5 window application? As shown below, I am trying to include the map into the rectangle area. *The rectangle black box is drawn on paint for reference purposes.
FYI I have tried out the solution code from the StackOverflow post but I can't seem to be able to resize the map.
WANTED OUTPUT
CURRENT CODE FOR REFERENCE
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton
from PyQt5 import QtWebEngineWidgets
import sys
from PyQt5 import QtGui
from PyQt5.QtCore import QRect
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "MAP PROJECT"
self.left = 200
self.top = 100
self.width = 1500
self.height = 800
self.initWindow()
def initWindow(self):
# set window title
self.setWindowTitle(self.title)
# set window geometry
# self.setGeometry(self.left, self.top, self.width, self.height)
# Disable PyQt 5 application from resizing
self.setFixedSize(self.width, self.height)
self.buttonUI()
self.show()
def buttonUI(self):
shortPathButton = QPushButton("Find shortest path", self)
# (set button location (x, x) set button size (y, y)
shortPathButton.setGeometry(QRect(30, 300, 120, 50))
button2 = QPushButton("Another path", self)
# (set button location (x, x) set button size (y, y)
button2.setGeometry(QRect(30, 370, 120, 50))
button3 = QPushButton("Another path", self)
# (set button location (x, x) set button size (y, y)
button3.setGeometry(QRect(30, 440, 120, 50))
# Below code is to connect the button to the function
# button.clicked.connect(self.ClickMe)
# Create function for shortest path (A* algorithm)
"""def ClickMe(self):
print("Hello World")"""
if __name__ == "__main__":
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())

The problem has nothing to do with a QWebEngineView or folium but how to place widgets inside the window, if so, then a solution is to use layouts in this case I will use the following structure: First a central widget is established, inside this one QHBoxLayout , and in the QHBoxLayout a QWidget is added as a container to the left side where a QVBoxLayout will be placed where the buttons will be, and to the right side the QWebEngineView:
import io
import sys
import folium
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setWindowTitle(self.tr("MAP PROJECT"))
self.setFixedSize(1500, 800)
self.buttonUI()
def buttonUI(self):
shortPathButton = QtWidgets.QPushButton(self.tr("Find shortest path"))
button2 = QtWidgets.QPushButton(self.tr("Another path"))
button3 = QtWidgets.QPushButton(self.tr("Another path"))
shortPathButton.setFixedSize(120, 50)
button2.setFixedSize(120, 50)
button3.setFixedSize(120, 50)
self.view = QtWebEngineWidgets.QWebEngineView()
self.view.setContentsMargins(50, 50, 50, 50)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QHBoxLayout(central_widget)
button_container = QtWidgets.QWidget()
vlay = QtWidgets.QVBoxLayout(button_container)
vlay.setSpacing(20)
vlay.addStretch()
vlay.addWidget(shortPathButton)
vlay.addWidget(button2)
vlay.addWidget(button3)
vlay.addStretch()
lay.addWidget(button_container)
lay.addWidget(self.view, stretch=1)
m = folium.Map(
location=[45.5236, -122.6750], tiles="Stamen Toner", zoom_start=13
)
data = io.BytesIO()
m.save(data, close_file=False)
self.view.setHtml(data.getvalue().decode())
if __name__ == "__main__":
App = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(App.exec())

Related

How to implement a shape selection panel for rendering in PyQt5?

I'm designing graphic editor. As a scene for drawing, I need to use exactly QGraphicsScene. I implemented adding rectangles and ellipses to the scene with two buttons.
I need to implement dragging the faigures from the panel to the canvas, approximately as in the picture:Shape Selection Panel
What widgets or buttons can I use for this custom panel? Maybe there is an information an example with the implementation of a similar panel?
The program code with the implementation of adding shapes and the interface image:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
# window class
class Window(QMainWindow):
def __init__(self):
super().__init__()
wid = QWidget()
self.setCentralWidget(wid)
# setting title
self.setWindowTitle("Paint with PyQt5")
# setting geometry to main window
self.setGeometry(100, 100, 800, 600)
# Defining a scene rect of 400x200, with it's origin at 0,0.
# If we don't set this on creation, we can set it later with .setSceneRect
self.scene = QGraphicsScene(0, 0, 400, 200)
# Set all items as moveable and selectable.
for item in self.scene.items():
item.setFlag(QGraphicsItem.ItemIsMovable)
item.setFlag(QGraphicsItem.ItemIsSelectable)
# Define our layout.
vbox = QVBoxLayout()
up = QPushButton("Rect")
up.clicked.connect(self.add_rect)
vbox.addWidget(up)
down = QPushButton("Elips")
down.clicked.connect(self.add_elips)
vbox.addWidget(down)
view = QGraphicsView(self.scene)
view.setRenderHint(QPainter.Antialiasing)
hbox = QHBoxLayout(self)
hbox.addLayout(vbox)
hbox.addWidget(view)
wid.setLayout(hbox)
def add_rect(self):
rect = QGraphicsRectItem(0, 0, 200, 50)
rect.setPos(50, 20)
rect.setFlag(QGraphicsItem.ItemIsMovable)
rect.setFlag(QGraphicsItem.ItemIsSelectable)
self.scene.addItem(rect)
def add_elips(self):
ellipse = QGraphicsEllipseItem(0, 0, 100, 100)
ellipse.setPos(75, 30)
ellipse.setFlag(QGraphicsItem.ItemIsMovable)
ellipse.setFlag(QGraphicsItem.ItemIsSelectable)
self.scene.addItem(ellipse)
# create pyqt5 app
App = QApplication(sys.argv)
# create the instance of our Window
window = Window()
# showing the window
window.show()
# start the app
sys.exit(App.exec())
Image of interface:
Image of interface

PYQT5 Lines around scroll area on GUI

good day, I wonder if someone could tell me why I end up with the following lines around the edge of my GUI.
The skeleton code is below which replicates the problem. I've tried adding stylesheets and QT alignment but to no avail. I think the issue could be with the QScrollArea(). I would love any help as this one has me stumped. Thank you
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.main_window()
def main_window(self):
self.setGeometry(0, 0, 500, 500)
self.grid = QGridLayout()
vbox = QVBoxLayout()
wrapper_widget = QWidget()
wrapper_widget.setLayout(self.grid)
# Bars
scroll = QScrollArea()
scroll.setWidget(wrapper_widget)
master_widget = QWidget()
vbox.addWidget(scroll)
master_widget.setLayout(vbox)
self.setCentralWidget(master_widget)
# Show
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())

How might one make a PyQt window which is avoided by other windows, like how windows avoid going on top of or below a panel?

I'd like to make a very simple PyQt5 panel, something a little like a very simple version of the MATE panel. In order for it to work as a panel, other windows of the desktop environment must not go under or above the panel, and when a window is maximised, it enlarges to the edge of the panel window, but does not overlap and go on top of the panel. How might this behaviour be implemented, or how might the window manager be directed to treat the panel appropriately?
In the LXPanel application preferences, one can see properties like these specified. What is happening in the background here and how can it be replicated by PyQt?
For the purposes of this question, let us assume that the panel is a window at the left edge of a display. Minimal working example code follows:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import (
QApplication,
QPushButton,
QToolTip,
QWidget,
)
def main():
app = QApplication(sys.argv)
interface = Interface()
sys.exit(app.exec_())
class Interface(QWidget):
def __init__(self):
super().__init__()
self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.setWindowFlags(Qt.FramelessWindowHint)
QToolTip.setFont(QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> widget.')
button_1 = QPushButton('Button 1', self)
button_1.setToolTip('This is a <b>QPushButton</b> widget')
button_1.resize(button_1.sizeHint())
button_1.move(40, 50) # button width: 80
button_2 = QPushButton('Button 2', self)
button_2.setToolTip('This is a <b>QPushButton</b> widget')
button_2.resize(button_2.sizeHint())
button_2.move(40, 80) # button width: 80
button_quit = QPushButton('Quit', self)
button_quit.setToolTip('Quit the application.')
button_quit.resize(button_quit.sizeHint())
button_quit.move(40, 110) # button width: 80
button_quit.clicked.connect(self.closeEvent)
self.resize(160, 600)
self.setWindowTitle('Panel')
self.show()
def closeEvent(self, event):
sys.exit(0)
if __name__ == '__main__':
main()
EDIT: With Python XLib, I appear to be a little closer to the answer. I appear to be reserving space of the right size, but with the window of the launcher appearing to the side of that reserved space. The updated code, this time including new XLib code, is shown below. Note that in order to run the example, both PyQt 5 and Python XLib are required:
sudo apt install python3-pyqt5 python3-xlib
The new minimal working example follows:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import (
QApplication,
QPushButton,
QToolTip,
QWidget,
)
from Xlib.display import Display
def main():
app = QApplication(sys.argv)
interface = Interface()
sys.exit(app.exec_())
class Interface(QWidget):
def __init__(self):
super().__init__()
self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.setWindowFlags(Qt.FramelessWindowHint)
QToolTip.setFont(QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> widget.')
button_1 = QPushButton('Button 1', self)
button_1.setToolTip('This is a <b>QPushButton</b> widget')
button_1.resize(button_1.sizeHint())
button_1.move(40, 50) # button width: 80
button_2 = QPushButton('Button 2', self)
button_2.setToolTip('This is a <b>QPushButton</b> widget')
button_2.resize(button_2.sizeHint())
button_2.move(40, 80) # button width: 80
button_quit = QPushButton('Quit', self)
button_quit.setToolTip('Quit the application.')
button_quit.resize(button_quit.sizeHint())
button_quit.move(40, 110) # button width: 80
button_quit.clicked.connect(self.closeEvent)
self.resize(160, 600)
self.setWindowTitle('Panel')
window_identification = self.winId().__int__()
window_height = self.height()
window_width = self.width()
print(f'window identification: {window_identification}')
print(f'window height: {window_height}, window width: {window_width}')
window = Window(window_identification)
window.reserve_space(window_width, 0, 0, 0)
self.show()
def closeEvent(self, event):
sys.exit(0)
class Window(object):
def __init__(self, window_ID):
self._display = Display()
self._window = self._display.create_resource_object('window', window_ID)
def reserve_space(self, left=0, right=0, top=0, bottom=0):
LEFT = int(left)
RIGHT = int(right)
TOP = int(top)
BOTTOM = int(bottom)
print([LEFT, RIGHT, TOP, BOTTOM])
self._window.change_property(
self._display.intern_atom('_NET_WM_STRUT'),
self._display.intern_atom('CARDINAL'),
32,
[LEFT, RIGHT, TOP, BOTTOM])
self._display.sync()
if __name__ == '__main__':
main()

How to make QTabWidget look transparent?

I want to make a simple GUI desktop application using python.
I've made a simple window with a background image, and I added a tab-widget on the right corner. It worked properly. But the tab-bar and tab contents area are white.
What I want is that the tab-widget's background shows it's parent window's background image (which means it's transparent). But I don't know how to do it.
Here is my working environment, code and screen shot:
Working environment:
Windows 7
Python 3.4
PyQt5 5.5
Source code:
# coding: utf-8
# There are some unnecessary module.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget, QWidget, QLabel, QHBoxLayout, QVBoxLayout, QGridLayout
from PyQt5.QtGui import QPixmap, QPalette, QBrush, QColor
from PyQt5.QtCore import Qt
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
tab1 = QWidget()
tab2 = QWidget()
vbox1 = self.makeTab1()
vbox2 = self.makeTab2()
tab1.setLayout(vbox1)
tab2.setLayout(vbox2)
tabs = QTabWidget()
tabs.addTab(tab1, "firstTab")
tabs.addTab(tab2, "secondTab")
picLabel = QLabel(self)
picFile = 'background_img.jpg'
pixmap = QPixmap(picFile)
palette = QPalette()
palette.setBrush(QPalette.Background, QBrush(pixmap))
hboxEX = QHBoxLayout()
hboxEX.addStretch(2)
hboxEX.addWidget(tabs)
hboxEX.setStretchFactor(tabs, 1)
vboxEX = QVBoxLayout()
vboxEX.addStretch(1)
vboxEX.addLayout(hboxEX)
vboxEX.setStretchFactor(hboxEX, 1)
self.setLayout(vboxEX)
self.setPalette(palette)
self.resize(pixmap.width(), pixmap.height())
self.show()
def makeTab1(self):
lbl1 = QLabel(self)
lbl2 = QLabel(self)
lbl3 = QLabel(self)
lbl1.setText("Google")
lbl2.setText("WikiPedia")
lbl3.setText("StackOverflow")
lbl1.setOpenExternalLinks(True)
lbl2.setOpenExternalLinks(True)
lbl3.setOpenExternalLinks(True)
vbox1 = QVBoxLayout()
vbox1.addWidget(lbl1)
vbox1.addWidget(lbl2)
vbox1.addWidget(lbl3)
return vbox1
def makeTab2(self):
lbl4 = QLabel(self)
lbl5 = QLabel(self)
lbl6 = QLabel(self)
lbl4.setText("Python")
lbl5.setText("CentOS")
lbl6.setText("MariaDB")
lbl4.setOpenExternalLinks(True)
lbl5.setOpenExternalLinks(True)
lbl6.setOpenExternalLinks(True)
vbox2 = QVBoxLayout()
vbox2.addWidget(lbl4)
vbox2.addWidget(lbl5)
vbox2.addWidget(lbl6)
return vbox2
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Screen shot:
What I tried:
I added these codes and it changed the tab's color. But it didn't make the tab area look transparent:
tabPalette = QPalette()
tabPalette.setColor(QPalette.Background, QColor("cyan"))
tab1.setAutoFillBackground(True)
tab1.setPalette(tabPalette)
I think it's a Windows problem. You might want to try to switch your application to a different style.
See this page of PyQt reference http://pyqt.sourceforge.net/Docs/PyQt4/qstyle.html
some sample code:
def changeStyle(self, styleName):
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create(styleName))
self.changePalette()
call it with:
changeStyle("plastique")

How to deal with layouts in PyQt4?

I want to display welcome label in middle of frame, how can I do that? It seems like layout problem as I googled but I haven't got final solution.
Here is the code:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
palette = QPalette()
palette.setBrush(QPalette.Background, QBrush(QPixmap("Login page.jpg")))
self.setPalette(palette)
self.setWindowTitle("Login Frame")
self.setWindowIcon(QIcon('logo.png'))
self.setGeometry(50, 50, 500, 300)
self.setFixedSize(500, 300)
self.addWidgets()
def addWidgets(self):
self.lblWelcome = QLabel("Welcome to Railway e-Ticketing System", self)
self.lblWelcome.move(100,30)
wcFont = QFont("Open Sans", 25)
self.lblWelcome.setFont(wcFont)
self.lblUid = QLabel("User ID:", self)
self.lblUid.move(100,80)
font = QFont("Open Sans", 10)
self.lneUid = QLineEdit(self)
self.lneUid.setFont(font)
self.lneUid.setFixedHeight(25)
self.lneUid.setFixedWidth(200)
self.lneUid.move(225, 80)
self.lblPass = QLabel("Password:", self)
self.lblPass.move(100, 130)
self.lnePass = QLineEdit(self)
self.lnePass.setEchoMode(QLineEdit.Password)
self.lnePass.setFixedHeight(25)
self.lnePass.setFixedWidth(200)
self.lnePass.move(225, 130)
self.lblInvalid = QLabel("",self)
self.lblInvalid.move(100, 180)
self.btnLogin = QPushButton("Login",self)
#btnLogin.resize(btnLogin.sizeHint())
self.btnLogin.move(175, 230)
self.btnLogin.clicked.connect(self.authenticate)
#self.authenticate()
self.btnReg = QPushButton("Register", self)
self.btnReg.move(300, 230)
#btnReg.clicked.connect(register)
self.show()
def authenticate(self):
uid = self.lneUid.text()
upass = self.lnePass.text()
if(len(uid.strip()) == 0 or len(upass.strip()) == 0):
palette = QPalette()
palette.setColor(QPalette.Foreground, Qt.darkRed)
self.lblInvalid.setPalette(palette)
self.lblInvalid.setText("*Invalid credentials .")
else:
self.lblInvalid.setText("")
def main():
app = QApplication(sys.argv)
LoginWin = Window()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
And here is the output:
You are using a QMainWindow which already has a layout with a central widget, a toolbar, a menu bar etc. The right way to use it is to define a central Widget, and put all your label and buttons in it. You didn't, so your label is not displayed properly.
But for your login frame, you clearly don't need all of this. You just need a QWidget:
import sys
from PyQt4 import QtCore,QtGui
class LoginFrame(QtGui.QWidget):
def __init__(self):
super(LoginFrame, self).__init__()
...
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
win = LoginFrame()
win.show()
sys.exit(app.exec_())
Your code should work with a QWidget, but I would still advise reading about box layout. Right now, you're using absolute positioning, which means you have to manually place your widget at a precise position, and you can't resize your window.
A box layout would be more flexible, and practical. For example you can use QFormLayout for the userID and password.
More about layouts on the ZetCode tutorial

Categories

Resources