Add scroll bar into tab PYQT5 - python

I wanted to create a scrollbar(pyqt5) into tab, base on example in link below I did some changes to fit my need but the scrollbar didn't show on tab and my charts become smaller.
example PyQt4 - how to add scrollbar into tabbed windows of fixed size?
import file https://filebin.net/u3m7m3x2k74wlm6l
import sys
import os
import pandas as pd
from PyQt5.QtWidgets import ( QApplication, QWidget,QHBoxLayout,QVBoxLayout,QPushButton,QTabWidget,QMainWindow,QGridLayout,QSizePolicy\
,QScrollArea,QGroupBox)
from PyQt5.QtGui import *
from PyQt5.QtCore import *
#import html
import plotly.offline as po
import plotly.express as px
import plotly.graph_objs as go
from PyQt5.QtWebEngineWidgets import *
class Win(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100,100, 1280,900)
self.GuiApp=App()
self.setCentralWidget(self.GuiApp)
self.show()
class Tab1(QWidget):
def __init__(self, parent=None):
super(Tab1, self).__init__(parent)
df = pd.read_csv(r'C:/Users/User/Desktop/Python-setup test/Plot122.csv')# need to download the file from https://filebin.net/u3m7m3x2k74wlm6l
data1 = px.line(df,x = 'Date', y ='AAPL.Open', color = 'Category')
fig4 = go.Figure(data1)
raw_html = '<html><head><meta charset="utf-8" />'
raw_html += '<script src="https://cdn.plot.ly/plotly-latest.min.js"></script></head>'
raw_html += '<body>'
raw_html += po.plot(fig4, include_plotlyjs=False, output_type='div')
raw_html += '</body></html>'
#fig_view
fig_view1 = QWebEngineView()
fig_view2 = QWebEngineView()
fig_view3 = QWebEngineView()
fig_view4 = QWebEngineView()
fig_view1.setHtml(raw_html)
fig_view1.setFixedSize(700,600)
fig_view1.show()
fig_view2.setHtml(raw_html)
fig_view2.setFixedSize(700,600)
fig_view2.show()
fig_view3.setHtml(raw_html)
fig_view3.setFixedSize(700,600)
fig_view3.show()
fig_view4.setHtml(raw_html)
fig_view4.setFixedSize(700,600)
fig_view4.show()
layoutC = QGridLayout()
layoutC.addWidget(fig_view1,0,0,1,1)
layoutC.addWidget(fig_view2,0,1,1,1)
layoutC.addWidget(fig_view3,1,0,1,1)
layoutC.addWidget(fig_view4,1,1,1,1)
self.setLayout(layoutC)
self.setSizePolicy(QSizePolicy.Maximum,QSizePolicy.Maximum)
class App(QWidget):
def __init__(self):
super().__init__()
self.layout = QGridLayout(self)
self.setLayout(self.layout)
#Button
BT1 = QPushButton('BT1',self)
self.layout.addWidget(BT1, 0,0,1,1)
##########################################TEST scrollbar in tab ################################################
tab1 = Tab1(self)
self.tabs = QTabWidget(self)
self.tabs.addTab(tab1, 'Page 1')
self.groupscrollbox = QGroupBox()
self.MVB = QVBoxLayout()
self.MVB.addWidget(self.tabs)
widgetTab = QWidget(self)
widgetTab.setLayout(QVBoxLayout())
widgetTab.layout().addWidget(self.groupscrollbox)
self.scroll = QScrollArea()
self.scroll.setWidget(widgetTab)
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setWidgetResizable(False)
self.scroll.setEnabled(True)
self.groupscrollbox.setLayout(self.MVB)
##########################################TEST scrollbar in tab ################################################
self.layout.addWidget(self.groupscrollbox, 0,2,13,1)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Win()
sys.exit(app.exec_())
I want to add scrollbar in the red box which the code between "TEST scrollbar in tab" to show all charts with "Date, It will be overlapped when maximize the window.
Below shows the Charts with "Date" below the charts

The solution is to put "tab1" is a QScrollArea, and that QScrollArea in the QTabWidget
class App(QWidget):
def __init__(self):
super().__init__()
bt1_button = QPushButton("BT1")
tab1 = Tab1()
scrollbar = QScrollArea(widgetResizable=True)
scrollbar.setWidget(tab1)
tabwidget = QTabWidget()
tabwidget.addTab(scrollbar, "Tab1")
layout = QGridLayout(self)
layout.addWidget(bt1_button, 0, 0)
layout.addWidget(tabwidget, 0, 1, 2, 1)

Related

how to display 2 buttons and 2 labels using pyqt5 in python?

I want to display in a QWidget windows 2 buttons and 2 label where the 2 buttons as on the same horizontal layout. and each button will have under it the label.
For this i use to library :
QHBoxLayout
QVBoxLayout
When i run the script it doesn't display all the created widgets.
it display 1 button and 1 label.
code:
import sys
from PyQt5 import QtWidgets
def basicWindow():
app = QtWidgets.QApplication(sys.argv)
windowExample = QtWidgets.QWidget()
buttonA = QtWidgets.QPushButton('Click!')
labelA = QtWidgets.QLabel('Label Example')
buttonb = QtWidgets.QPushButton('Click 2!')
labelb = QtWidgets.QLabel('Label Example 2')
v_box_H = QtWidgets.QHBoxLayout()
# v_box_H2 = QtWidgets.QHBoxLayout()
v_box = QtWidgets.QVBoxLayout()
v_box.addWidget(buttonA)
v_box.addWidget(labelA)
v_box2 = QtWidgets.QVBoxLayout()
v_box2.addWidget(buttonb)
v_box2.addWidget(labelb)
v_box_H.addLayout(v_box)
windowExample.setLayout(v_box)
windowExample.setLayout(v_box2)
windowExample.setWindowTitle('PyQt5 Lesson 4')
windowExample.show()
sys.exit(app.exec_())
basicWindow()
If you run the application from terminal / CMD you get the error:
QWidget::setLayout: Attempting to set QLayout "" on QWidget "", when the QLayout already has a parent
Try it:
import sys
from PyQt5 import QtWidgets
def basicWindow():
app = QtWidgets.QApplication(sys.argv)
windowExample = QtWidgets.QWidget()
buttonA = QtWidgets.QPushButton('Click!')
labelA = QtWidgets.QLabel('Label Example')
buttonb = QtWidgets.QPushButton('Click 2!')
labelb = QtWidgets.QLabel('Label Example 2')
v_box_H = QtWidgets.QHBoxLayout(windowExample) # + windowExample
# v_box_H2 = QtWidgets.QHBoxLayout()
v_box = QtWidgets.QVBoxLayout()
v_box.addWidget(buttonA)
v_box.addWidget(labelA)
v_box2 = QtWidgets.QVBoxLayout()
v_box2.addWidget(buttonb)
v_box2.addWidget(labelb)
v_box_H.addLayout(v_box)
v_box_H.addLayout(v_box2) # +++
# windowExample.setLayout(v_box) # -
# windowExample.setLayout(v_box2) # -
windowExample.setWindowTitle('PyQt5 Lesson 4')
windowExample.show()
sys.exit(app.exec_())
basicWindow()

PyQt5: Slot in separate file not being called

I currently have a basic GUI right now with each page in its own file. I can navigate to and from each page with no problem, but I'm having difficulty simply passing a search query to another Widget. Here's where I setup the connections in the main file:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import search
import watching
import helpinfo
import results
class MainWindow(QMainWindow):
def __init__(self, parent=None):
'''
Constructor
'''
QMainWindow.__init__(self, parent)
self.centralWidget = QStackedWidget()
self.setCentralWidget(self.centralWidget)
self.startScreen = Start(self)
self.searchScreen = search.Search(self)
self.watchingScreen = watching.Watching(self)
self.helpInfoScreen = helpinfo.HelpInfo(self)
self.resultsScreen = results.Results(self)
self.centralWidget.addWidget(self.startScreen)
self.centralWidget.addWidget(self.searchScreen)
self.centralWidget.addWidget(self.watchingScreen)
self.centralWidget.addWidget(self.helpInfoScreen)
self.centralWidget.addWidget(self.resultsScreen)
self.centralWidget.setCurrentWidget(self.startScreen)
self.startScreen.searchClicked.connect(lambda: self.centralWidget.setCurrentWidget(self.searchScreen))
self.startScreen.watchingClicked.connect(lambda: self.centralWidget.setCurrentWidget(self.watchingScreen))
self.startScreen.helpInfoClicked.connect(lambda: self.centralWidget.setCurrentWidget(self.helpInfoScreen))
self.searchScreen.searchSubmitted.connect(lambda: self.centralWidget.setCurrentWidget(self.resultsScreen))
self.searchScreen.passQuery.connect(lambda: self.resultsScreen.grabSearch) #This is the problem line
self.searchScreen.clicked.connect(lambda: self.centralWidget.setCurrentWidget(self.startScreen))
self.watchingScreen.clicked.connect(lambda: self.centralWidget.setCurrentWidget(self.startScreen))
self.helpInfoScreen.clicked.connect(lambda: self.centralWidget.setCurrentWidget(self.startScreen))
self.resultsScreen.clicked.connect(lambda: self.centralWidget.setCurrentWidget(self.startScreen))
Here's the search file:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class Search(QWidget):
clicked = pyqtSignal()
searchSubmitted = pyqtSignal()
passQuery = pyqtSignal(str)
def __init__(self, parent=None):
super(Search, self).__init__(parent)
logo = QLabel(self)
pixmap = QPixmap('res/logo.png')
logo.setPixmap(pixmap)
logo.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
logo.setAlignment(Qt.AlignCenter)
self.textbox = QLineEdit(self)
label = QLabel(text="This is the search page.")
label.setAlignment(Qt.AlignCenter)
button = QPushButton(text='Submit')
button.clicked.connect(lambda: self.submitSearch())
button2 = QPushButton(text='Go back.')
button2.clicked.connect(self.clicked.emit)
layout = QVBoxLayout()
layout.addWidget(logo)
layout.addWidget(label)
layout.addWidget(self.textbox)
layout.addWidget(button)
layout.addWidget(button2)
layout.setAlignment(Qt.AlignTop)
self.setLayout(layout)
def submitSearch(self):
self.searchSubmitted.emit()
self.passQuery.emit(self.textbox.text())
And here is the results file:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Results(QWidget):
clicked = pyqtSignal()
def __init__(self, parent=None):
super(Results, self).__init__(parent)
# Create Logo
logo = QLabel(self)
pixmap = QPixmap('res/logo.png')
logo.setPixmap(pixmap)
logo.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
logo.setAlignment(Qt.AlignCenter)
# Create page contents
label = QLabel(text="This is the results page. If you see this, it's still broken.")
label.setAlignment(Qt.AlignCenter)
button = QPushButton(text='Add to watching.')
button2 = QPushButton(text='Go back.')
button2.clicked.connect(self.clicked.emit)
# Set up layout
layout = QVBoxLayout()
layout.addWidget(logo)
layout.addWidget(label)
layout.addWidget(button)
layout.addWidget(button2)
layout.setAlignment(Qt.AlignTop)
self.setLayout(layout)
#pyqtSlot(str)
def grabSearch(self, str):
print(str)
self.label.setText(str)
The way I understand it, what I have right now should be working. When the user submits some text on the search page, it calls the submitSearch() function. That function emits two signals: the first, searchSubmitted, changes the screen to the results screen (this works as intended). The second, passQuery, should be passing the contents of the textbox to the connected function grabSearch() in the results file. However, the passQuery never seems to be caught by the results page despite being connected. I've verified with print statements that it is being emitted, but that's it.
What am I missing here?
Your code has the following errors:
If you are going to use a lambda to make the connection you must invoke the function with the arguments.
self.searchScreen.passQuery.connect(lambda text: self.resultsScreen.grabSearch(text))
But it is better to use the direct connection since the signatures are the same:
self.searchScreen.passQuery.connect(self.resultsScreen.grabSearch)
Another error is that the results.py label must be a member of the class:
self.label = QLabel(text="This is the results page. If you see this, it's still broken.") # <--
self.label.setAlignment(Qt.AlignCenter) # <--
# ..
# Set up layout
layout = QVBoxLayout()
layout.addWidget(logo)
layout.addWidget(self.label) # <--
And finally do not use reserved words like str, change to:
#pyqtSlot(str)
def grabSearch(self, text):
self.label.setText(text)

gap between QListWidget items/icons

I would like to remove the gap between my QListWidget items in my textureIconChart QListWidget. It is populated with items set with pixmap icons. I am using QListWidget set to a QHBoxLayout, which is set to a QVBoxLayout.
import maya.cmds as cmds
import os
import maya.OpenMayaUI as mui
from PySide2 import QtWidgets,QtCore,QtGui
import shiboken2
class texture_replacer():
def texture_linker_UI(self):
windowName = "name"
if cmds.window(windowName,exists = True):
cmds.deleteUI(windowName, wnd = True)
pointer = mui.MQtUtil.mainWindow()
parent = shiboken2.wrapInstance(long(pointer),QtWidgets.QWidget)
window = QtWidgets.QMainWindow(parent)
window.setObjectName(windowName)
window.setWindowTitle(windowName)
window.setMinimumSize(450,650)
window.setMaximumSize(600,400)
mainWidget = QtWidgets.QWidget()
window.setCentralWidget(mainWidget)
verticalLayout = QtWidgets.QVBoxLayout(mainWidget)
self.textureIconChartLayout = QtWidgets.QVBoxLayout()
textureIconsLayout = QtWidgets.QHBoxLayout()
self.textureIconChartLayout.addLayout(textureIconsLayout)
verticalLayout.addLayout(self.textureIconChartLayout)
self.textureIconChart = QtWidgets.QListWidget()
self.textureIconChart.setViewMode(QtWidgets.QListWidget.IconMode)
self.textureIconChart.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.textureIconChart.setDragEnabled(0)
self.textureIconChart.setMaximumWidth(290)
self.populateListWidget()
textureIconsLayout.addWidget(self.textureIconChart)
textureIconsLayout.setSpacing(0)
textureIconsLayout.setContentsMargins(0,0,0,0)
tr = texture_replacer()
tr.texture_linker_UI()

How can I make QMainWindow refresh when QWidget is closed?[PyQt5]

I am currently making an application with PyQt5 and I am trying to find a way to refresh the main window when the QWidget it calls is closed.
My main window page looks like this:
import sys
import glob
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from addClass import addClass
class TeacherMain(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.initUI()
def initUI(self):
x = 30
y = 80
buttonContainer = QLabel(self)
buttonContainer.setStyleSheet("background-color: #5D4A41;")
buttonContainer.move(20, 70)
buttonContainer.resize(1240, 550)
buttonContainer.show()
classes = glob.glob("Folder/*.csv")
classes = [j.strip("Folder/") for j in [i.strip('.csv') for i in classes]]
for k in classes:
classButton = QPushButton(k, self)
classButton.move(x, y)
classButton.setStyleSheet("background-color: green;")
classButton.resize(143, 143)
classButton.clicked.connect(self.viewClass)
x += 153 ## Increase value of x.
if x >= 1235:
y += 153
x = 30
addClass = QPushButton("Add Class...", self)
addClass.move(x, y)
addClass.resize(143, 143)
addClass.clicked.connect(self.createClass)
quit = QPushButton("Quit", self)
quit.setStyleSheet("background-color: white;")
quit.move(630, 645)
self.setStyleSheet("background-color: #AD9A90;")
self.setWindowTitle("SheikhCoin Teacher")
self.setFixedSize(1280, 690)
self.show()
def createClass(self):
self.new_window = addClass()
self.new_window.show()
def main():
app = QApplication(sys.argv)
main = TeacherMain()
main.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
And my QWidget looks like this:
class addClass(QWidget):
def __init__(self):
QWidget.__init__(self)
self.initUI()
def initUI(self, granted):
className = QLabel("Class Name", self)
className.setStyleSheet("font: 14pt Comic Sans MS")
self.nameBox = QLineEdit(self)
self.nameBox.resize(200, 20)
self.nameBox.setStyleSheet("background-color: white;")
add = QPushButton("Add Class", self)
add.setStyleSheet("background-color: white;")
add.clicked.connect()
def create(self):
name = self.nameBox.text()
path = "Folder/" + name + ".csv"
classRows = [["Student Key", "Prefix", "Forename", "Surname", "Tutor"]]
with open(path, 'w') as file:
write = csv.writer(newClass, delimiter=',')
write.writerows(classRows)
self.close()
Once the file is created in the QWidget, I would like the Main Window to update to show the file that has just been added as a button, as is done with the files already in Folder when the Main Window is first opened.
Anybody have any idea how to do this?

Add custom items to QListWidget

How can I add customized items to a QListWidget with a background color that I choose, and add a bottom border to each item, like this draft example in the picture below.
This is the code that I wrote:
from PyQt5 import QtWidgets, QtGui
import sys
class CustomListHead(QtWidgets.QWidget):
def __init__(self):
super(CustomListHead, self).__init__()
self.project_title = QtWidgets.QLabel("Today")
self.set_ui()
def set_ui(self):
grid_box = QtWidgets.QGridLayout()
grid_box.addWidget(self.project_title, 0, 0)
self.setLayout(grid_box)
self.show()
class CustomListItem(QtWidgets.QWidget):
def __init__(self):
super(CustomListItem, self).__init__()
self.project_title = QtWidgets.QLabel("Learn Python")
self.task_title = QtWidgets.QLabel("Learn more about forms, models and include")
self.set_ui()
def set_ui(self):
grid_box = QtWidgets.QGridLayout()
grid_box.addWidget(self.project_title, 0, 0)
grid_box.addWidget(self.task_title, 1, 0)
self.setLayout(grid_box)
self.show()
class MainWindowUI(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindowUI, self).__init__()
self.list_widget = QtWidgets.QListWidget()
self.set_ui()
def set_ui(self):
custom_head_item = CustomListHead()
item = QtWidgets.QListWidgetItem(self.list_widget)
item.setSizeHint(custom_head_item.sizeHint())
self.list_widget.setItemWidget(item, custom_head_item)
self.list_widget.addItem(item)
custom_item = CustomListItem()
item = QtWidgets.QListWidgetItem(self.list_widget)
item.setSizeHint(custom_item.sizeHint())
self.list_widget.addItem(item)
self.list_widget.setItemWidget(item, custom_item)
vertical_layout = QtWidgets.QVBoxLayout()
vertical_layout.addWidget(self.list_widget)
widget = QtWidgets.QWidget()
widget.setLayout(vertical_layout)
self.setCentralWidget(widget)
self.show()
app = QtWidgets.QApplication(sys.argv)
ui = MainWindowUI()
sys.exit(app.exec_())
I see you have QListWidgetItem with you.
From documentation you can customize each widget item, customize it and add to your listwidget:
The appearance of the text can be customized with setFont(), setForeground(), and setBackground(). Text in list items can be aligned using the setTextAlignment() function. Tooltips, status tips and "What's This?" help can be added to list items with setToolTip(), setStatusTip(), an
d setWhatsThis().
http://doc.qt.io/qt-5/qlistwidgetitem.html#details

Categories