Seite 1 von 1
Erweiterte Buttenbar
Verfasst: Dienstag 17. Januar 2023, 17:38
von Nobuddy
Hallo zusammen,
ich möchte eine Buttonbar unten erstellen, die unter anderem ein komplettes Suchfeld enthält, mit der Option nach unten zu erweitern, z.B. mit "find, replace, replace all".
Ich versuche mit QGridLayout zwei horizonzale Bereiche zu erstellen, leider ist alles in einem Bereich.
Mein Code ist lauffähig.
Hoffe, Ihr könnt mir dabei helfen
Code: Alles auswählen
import sys
from PyQt5.QtCore import (
Qt,
)
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QMdiArea,
QComboBox,
QGridLayout,
QLineEdit,
QPushButton,
QToolBar,
QWidget,
)
from PyQt5.QtGui import (
QFont,
)
class ButtonBar(QToolBar):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.parent = parent
self.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
self.verticalLayout = QVBoxLayout()
self.layout = QGridLayout()
fontSize = 14
self.font = QFont('NimbusSansL', fontSize)
parent.searchComboSelection = 'AUTO', 'COMBO', 'SEARCH', 'REPLACE'
firstBarBelow = ['search', 'back', 'next']
secodBarBelow = ['find', 'replace', 'replace all']
for y, bar in enumerate([firstBarBelow, secodBarBelow]):
for x, button in enumerate(bar):
if button == 'search':
# create cömbobox
self.setComboBox(fontSize)
# create searchfield in toolbar
self.setSearchArea(fontSize)
self.layout.addWidget(self.setPushButton(button), y, x)
self.setLayout(self.layout)
def setComboBox(self, fontSize):
cb = QComboBox(self)
cb.setEnabled(True)
cb.setObjectName('combobox')
[cb.addItem(text) for text in self.parent.searchComboSelection]
cb.setCurrentText('AUTO')
self.comboState = cb.currentText()
cb.activated[str].connect(self.onChanged)
cb.setFont(self.font)
self.addWidget(cb)
def setSearchArea(self, fontSize):
sF = QLineEdit()
f = sF.font() # lineedit current font
f.setPointSize(fontSize) # change it's size
sF.setFont(f) # set font
sF.setFocusPolicy(Qt.StrongFocus)
sF.setPlaceholderText('Eingabe Suche')
sF.setObjectName('searchField')
sF.resize(200,40)
sF.setMaximumWidth(400)
sF.setMinimumHeight(40)
sF.setReadOnly(False) # True / False (write)
sF.installEventFilter(self)
self.addWidget(sF)
def setPushButton(self, button):
pushbutton = QPushButton(button.capitalize())
pushbutton.setLayout(self.layout)
pushbutton.setCheckable(False) # True / False
pushbutton.setEnabled(True)
pushbutton.setFont(self.font)
self.addWidget(pushbutton)
def onChanged(self, text):
print('onChanged', text)
class WindowMDI(QMainWindow):
def __init__(self):
super().__init__()
self.mdi = QMdiArea()
# set geomerty
self.setGeometry(100, 300, 1000, 500)
# toolbar below
self.addToolBar(Qt.BottomToolBarArea, ButtonBar(parent=self))
self.setCentralWidget(self.mdi)
def main():
App = QApplication(sys.argv)
obj = WindowMDI()
title = 'PyQt5 QMainWindow'
obj.setWindowTitle(title)
obj.show()
sys.exit(App.exec())
if __name__ == '__main__':
main()
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 11:19
von __deets__
Die gute Nachricht: ich habe nur eine Zeile entfernen muessen, und es lief tatsaechlich. Die schlechte Nachricht: mir ist unklar, was genau du erreichen willst, und was nicht funktioniert. Fuer mich sieht es gut aus(tm), aber das mag Ignoranz meinerseits sein.
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 11:24
von __deets__
Nachtrag: ich sehe gerade eine ganze Reihe von Fehlermeldungen/Warnungen, die sich danach anhoeren, dass die relevant sind:
Code: Alles auswählen
QLayout: Cannot add a null widget to QGridLayout/
QLayout: Cannot add a null widget to QGridLayout/
QLayout: Cannot add a null widget to QGridLayout/
QLayout: Cannot add a null widget to QGridLayout/
QLayout: Cannot add a null widget to QGridLayout/
QLayout: Cannot add a null widget to QGridLayout/
QWidget::setLayout: Attempting to set QLayout "" on ButtonBar "", which already has a layout
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 11:46
von Nobuddy
Hallo __deets__,
ja die Zeile habe ich auch entfernt und habe die gleiche Meldungen, wie Du.
Vielleicht habe ich da den falschen Ansatz gewählt.
Beim Erstellen der unteren ButtonBar, ist eine ComboBox mit Suchfeld integriert. Eigentlich möchte ich erreichen, dass bei der Auswahl "REPLACE" der ComboBox, sich dann unterhalb der ButtonBar eine zweite Zeile mit den Buttons "find, replace, replace all" erscheint, die dann wieder verschwindet, wenn diese nicht benötigt wird.
Ich habe erst mal versucht, beide Button Zeilen zu erstellen, was so nicht funktioniert.
Vielleicht kannst Du mir da die richtige Richtung zeigen?
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 12:11
von __deets__
Ok, auf die Gefahr hin wieder der boese Bube zu sein: warum? Es gibt wenig, was mehr nervt als nervoes rumzuckende UIs. Es gibt sowas, zB bei FreeCAD und seine Workbenches. Das ist aber ein etwas anderer Ansatz, da waehlt man quasi eine andere Art, mit dem Projekt umzugehen. Also eher sowas wie eine Konfiguration, die man untere mehreren auswaehlt.
Sowas wie du hier hast wuerde ich immer nur mit enable/disable machen, oder mit dedizierten Toolbars, die der User an/ausschalten kann. So ein geflacker, bei der dann die ComboBox unter deiner Maus verschwindet, weil du einen anderen Eintrag ausgewaehlt hast, ist der Horror. Dieser Fall tritt ein, wenn jemand (was Toolbars koennen, und User sich dann eben so einstellen) die Toolbar nach unten zieht. Und du ballerst dann eine zweite Zeile da rein, und die ComboBox springt davon...
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 12:20
von Nobuddy
Ok, das ist ein gutes Argument, mein Vorhaben anderst umzusetzen.
Die ButtonBar bei ComboBox Auswahl "REPLACE" zu ersetzen.
Diese würde dann die ComboBox, das Suchfeld und die Buttons "find, replace, replace all" enthalten. Wenn die ComboBox Auswahl NICHT "REPLACE" ist, dann die "Haupt-ButtonBar".
Das wäre so wohl besser.
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 12:43
von Nobuddy
Habe meinen Code umgeschrieben, so funktioniert es.
Code: Alles auswählen
import sys
from PyQt5.QtCore import (
Qt,
)
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QMdiArea,
QComboBox,
QGridLayout,
QLineEdit,
QPushButton,
QToolBar,
QWidget,
)
from PyQt5.QtGui import (
QFont,
)
class ButtonBar(QToolBar):
def __init__(self, buttons, parent=None):
super().__init__(parent=parent)
self.parent = parent
self.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
fontSize = 14
self.gridLayout = QGridLayout()
self.font = QFont('NimbusSansL', fontSize)
y = 0
for x, name in enumerate(buttons):
if name == 'search':
# create cömbobox
selection = 'AUTO', 'COMBO', 'SEARCH', 'REPLACE'
parent.searchComboSelection = selection
ComboBox(name, selection, parent.onChanged, self.font,
parent=self)
# create searchfield in toolbar
TextField(name, fontSize, parent=self)
pb = PushButton(name, self.gridLayout, parent=self)
self.gridLayout.addWidget(pb, y, x)
class ComboBox(QComboBox):
def __init__(self, name, selection, func, font, parent=None):
super().__init__(parent=parent)
self.setEnabled(True)
try:
self.setObjectName('{}Combo'.format(name.lower()))
except AttributeError:
self.setObjectName('combobox')
[self.addItem(name) for name in selection]
self.setCurrentText('AUTO')
self.comboState = self.currentText()
self.activated[str].connect(func)
self.setFont(font)
parent.addWidget(self)
class TextField(QLineEdit):
def __init__(self, name, fontSize, parent=None):
super().__init__(parent=parent)
f = self.font() # lineedit current font
f.setPointSize(fontSize) # change it's size
self.setFont(f) # set font
self.setFocusPolicy(Qt.StrongFocus)
self.setPlaceholderText('Eingabe')
self.setObjectName('{}Field'.format(name.lower()))
self.resize(200,40)
self.setMaximumWidth(400)
self.setMinimumHeight(40)
self.setReadOnly(False) # True / False (write)
self.installEventFilter(parent)
parent.addWidget(self)
class PushButton(QWidget):
def __init__(self, button, layout, parent=None):
super().__init__(parent=parent)
pb = QPushButton(button.capitalize())
pb.setLayout(layout)
pb.setCheckable(False) # True / False
pb.setEnabled(True)
pb.setFont(parent.font)
parent.addWidget(pb)
class WindowMDI(QMainWindow):
def __init__(self):
super().__init__()
self.mdi = QMdiArea()
# set geomerty
self.setGeometry(100, 300, 1000, 500)
# toolbar below
self.firstBarBelow = ['search', 'back', 'next']
self.secondBarBelow = ['search', 'find', 'replace', 'replace all']
self.firstBB = ButtonBar(self.firstBarBelow, parent=self)
self.addToolBar(Qt.BottomToolBarArea, self.firstBB)
self.setCentralWidget(self.mdi)
def onChanged(self, name):
print('onChanged', name)
if name == 'REPLACE':
self.firstBB.setParent(None)
self.secondBB = ButtonBar(
self.secondBarBelow, parent=self
)
self.addToolBar(
Qt.BottomToolBarArea, self.secondBB
)
else:
self.secondBB.setParent(None)
self.firstBB = ButtonBar(
self.firstBarBelow, parent=self
)
self.addToolBar(
Qt.BottomToolBarArea, self.firstBB
)
def main():
App = QApplication(sys.argv)
obj = WindowMDI()
title = 'PyQt5 QMainWindow'
obj.setWindowTitle(title)
obj.show()
sys.exit(App.exec())
if __name__ == '__main__':
main()
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 12:50
von __deets__
Nicht fuer mich:
Code: Alles auswählen
$ python3 /tmp/test.py
onChanged COMBO
Traceback (most recent call last):
File "/tmp/test.py", line 119, in onChanged
self.secondBB.setParent(None)
AttributeError: 'WindowMDI' object has no attribute 'secondBB'
onChanged SEARCH
Traceback (most recent call last):
File "/tmp/test.py", line 119, in onChanged
self.secondBB.setParent(None)
AttributeError: 'WindowMDI' object has no attribute 'secondBB'
onChanged REPLACE
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 14:55
von Nobuddy
Hatte auch die Fehlermeldung. Bei nochmaligem Testen kam diese aber nicht mehr ... komisch.
Ich habe folgendes abgeändert.
Code: Alles auswählen
def onChanged(self, name):
print('onChanged', name)
if name == 'REPLACE':
self.replaceBar = True
self.firstBB.setParent(None)
self.firstBB.deleteLater() # <<<<<<<<<<<<<
self.secondBB = ButtonBar(
self.secondBarBelow, parent=self
)
self.addToolBar(
Qt.BottomToolBarArea, self.secondBB
)
else:
self.replaceBar = False
self.secondBB.setParent(None)
self.secondBB.deleteLater() # <<<<<<<<<<<<<
self.firstBB = ButtonBar(
self.firstBarBelow, parent=self
)
self.addToolBar(
Qt.BottomToolBarArea, self.firstBB
)
ButtonBar wird entfernt und bei Bedarf neu erstellt.
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 15:03
von Axel-WAK
Das funktioniert so auch nicht, beim Wählen von Combo hast Du die Widgets doppelt. Du solltest das Konzept neu überdenken.
Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 16:22
von Nobuddy
Bin dabei, gebe nicht so schnell auf

Re: Erweiterte Buttenbar
Verfasst: Mittwoch 18. Januar 2023, 18:39
von Axel-WAK
Wäre es nicht sogar sinnvoller alle Buttons zu haben ohen erst eine ComboBox zu bemühen?
Code: Alles auswählen
import sys
from PyQt5.QtCore import (
Qt,
)
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QMdiArea,
QGridLayout,
QLineEdit,
QPushButton,
QToolBar,
QWidget,
)
class ButtonBar(QToolBar):
def __init__(self, buttons, parent=None):
super().__init__(parent=parent)
self.setStyleSheet("""QToolBar{spacing: 3px; margin-top: 5px; border: 0px;}
QPushButton{font-family:NimbusSansL; font-size: 14pt;}
QLineEdit{font-family:NimbusSansL; font-size: 14pt;}""")
self.parent = parent
self.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
self.gridLayout = QGridLayout()
y = 0
for x, name in enumerate(buttons):
if name == 'search':
# create searchfield in toolbar
TextField(name, parent=self)
else:
pb = PushButton(name, self.gridLayout, parent=self)
self.gridLayout.addWidget(pb, y, x)
class TextField(QLineEdit):
def __init__(self, name, parent=None):
super().__init__(parent=parent)
self.setFocusPolicy(Qt.StrongFocus)
self.setPlaceholderText('Eingabe')
self.setObjectName('{}Field'.format(name.lower()))
self.resize(200, 30)
self.setMaximumWidth(400)
self.setMinimumHeight(32)
self.setReadOnly(False) # True / False (write)
self.installEventFilter(parent)
parent.addWidget(self)
class PushButton(QWidget):
def __init__(self, button, layout, parent=None):
super().__init__(parent=parent)
pb = QPushButton(button.capitalize())
pb.setLayout(layout)
pb.setCheckable(False) # True / False
pb.setEnabled(True)
parent.addWidget(pb)
class WindowMDI(QMainWindow):
def __init__(self):
super().__init__()
self.mdi = QMdiArea()
# set geomerty
self.setGeometry(100, 300, 1000, 500)
self.setContentsMargins(10, 10, 10 ,10)
# toolbar below
self.secondBarBelow = ['search', 'find', 'replace', 'replace all', 'back', 'next']
self.firstBB = ButtonBar(self.secondBarBelow, parent=self)
self.addToolBar(Qt.BottomToolBarArea, self.firstBB)
self.setCentralWidget(self.mdi)
def main():
App = QApplication(sys.argv)
obj = WindowMDI()
title = 'PyQt5 QMainWindow'
obj.setWindowTitle(title)
obj.show()
sys.exit(App.exec())
if __name__ == '__main__':
main()
Re: Erweiterte Buttenbar
Verfasst: Donnerstag 19. Januar 2023, 10:59
von Nobuddy
Nein, ich möchte das nach Anwendungsfall steuern.
Je nach Anwendungsfall, werden nicht alle Buttons benötigt, bzw. andere Buttons benötigt.
Mittlerer Weile, bin ich auf dem richtigen Weg.
Code: Alles auswählen
import sys
from PyQt5.QtCore import (
Qt,
)
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QMdiArea,
QComboBox,
QGridLayout,
QLineEdit,
QTextEdit,
QPushButton,
QToolBar,
QWidget,
)
from PyQt5.QtGui import (
QFont,
)
# Areas of buttonbar below
AREAS = {
'start' : ['search'],
'table' : ['search', 'back', 'next', 'new', 'delete'],
'replace' : ['search', 'find', 'replace', 'find all', 'replace all'],
}
class ButtonBar(QToolBar):
def __init__(self, area, parent=None):
super().__init__(parent=parent)
self.parent = parent
try:
className = parent.object.__class__.__name__
except AttributeError:
# not parent.object
try:
# if test
parent.test
className = True
except AttributeError:
className = False
self.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
fontSize = 14
gridLayout = QGridLayout()
func = parent.mainBarCallback
self.font = QFont('NimbusSansL', fontSize)
y = 0
for x, name in enumerate(AREAS[area]):
self.addSeparator()
if name == 'search':
# create cömbobox
selection = 'AUTO', 'COMBO', 'SEARCH', 'REPLACE'
parent.searchComboSelection = selection
self.cb = ComboBox(name, selection, self.comboChanged,
self.font, parent=self)
# create searchfield in toolbar
textField = TextField(name, fontSize, parent=self)
self.addSeparator()
if name == 'search' and 'find' in AREAS[area]:
self.cb.setCurrentText('REPLACE')
continue
pb = PushButton(name, gridLayout, func, parent=self)
if not className:
self.cb.setEnabled(False)
textField.setReadOnly(True)
pb.setEnabled(False)
self.addSeparator()
gridLayout.addWidget(QWidget(pb), y, x)
def comboChanged(self, text):
print('comboChanged: ', text)
self.comboState = text
self.buttonWidget['searchCombo'].setCurrentText(text)
self.buttonWidget['searchField'].setText('')
self.buttonWidget['searchField'].setFocus()
self.buttonBarCallback(text)
def buttonBarCallback(self, name):
print('buttonBarCallback: ', name)
self.parent.buttonArea.setParent(None)
self.parent.buttonArea.deleteLater()
self.parent.buttonArea.close()
self.searchBar = False
self.replaceBar = False
if name == 'REPLACE':
self.replaceBar = True
area = name.lower()
else:
self.searchBar = True
area = 'start'
self.parent.buttonArea = ButtonBar(area, parent=self.parent)
self.parent.addToolBar(
Qt.BottomToolBarArea, self.parent.buttonArea)
self.cb.setCurrentText(name)
class ComboBox(QComboBox):
def __init__(self, name, selection, func, font, parent=None):
super().__init__(parent=parent)
self.setEnabled(True)
try:
self.setObjectName('{}Combo'.format(name.lower()))
except AttributeError:
self.setObjectName('combobox')
[self.addItem(name) for name in selection]
self.setCurrentText('AUTO')
self.comboState = self.currentText()
self.activated[str].connect(func)
self.setFont(font)
parent.buttonWidget = {'searchCombo' : self}
parent.addWidget(self)
class TextField(QLineEdit):
def __init__(self, name, fontSize, parent=None):
super().__init__(parent=parent)
self.parent = parent
f = self.font() # lineedit current font
f.setPointSize(fontSize) # change it's size
self.setFont(f) # set font
self.setFocusPolicy(Qt.StrongFocus)
self.setPlaceholderText('Eingabefeld')
self.setObjectName('{}Field'.format(name.lower()))
self.resize(200,40)
self.setMaximumWidth(400)
self.setMinimumHeight(40)
self.setReadOnly(False) # True / False (write)
self.installEventFilter(parent)
self.textChanged[str].connect(self.searchFieldCallback)
parent.buttonWidget['searchField'] = parent.searchField = self
parent.addWidget(self)
def searchFieldCallback(self, name):
print('searchFieldCallback: ', name)
# state to combobox
state = self.parent.buttonWidget['searchCombo'].currentText()
if state == 'COMBO':
# get text to search field
name = name.upper()
self.parent.buttonWidget['searchField'].setText(name)
self.parent.buttonSearch()
self.parent.buttonWidget['searchField'].setFocus()
class PushButton(QPushButton):
def __init__(self, name, layout, func, parent=None):
super().__init__(parent=parent)
self.setText(name.capitalize())
self.clicked.connect(func)
self.setLayout(layout)
self.setCheckable(False) # True / False
self.setEnabled(True)
self.setFont(parent.font)
try:
parent.buttonWidget[name] = self
except AttributeError:
parent.buttonWidget = {name : self}
parent.addWidget(self)
class WindowMDI(QMainWindow):
def __init__(self):
super().__init__()
self.mdi = QMdiArea()
# set geomerty
self.setGeometry(100, 300, 1000, 500)
# toolbar below
self.test = True
self.buttonArea = ButtonBar('start', parent=self)
self.addToolBar(Qt.BottomToolBarArea, self.buttonArea)
self.buttonBarMemory = dict()
self.toolBarMemory = dict()
# attribute for messagebox
self.resultMB = QTextEdit()
self.resultMB.setPlainText('False')
self.setCentralWidget(self.mdi)
#@pyqtSlot()
def mainBarCallback(self):
self.buttonJob = self.sender().text().lower()
print('mainBarCallback: ', self.buttonJob)
jobArea = {
'search' : self.jobFunc,
'back' : self.jobFunc,
'next' : self.jobFunc,
'new' : self.jobFunc,
'delete' : self.jobFunc,
'find' : self.jobFunc,
'replace' : self.jobFunc,
'find all' : self.jobFunc,
'replace all' : self.jobFunc,
}[self.buttonJob]()
def jobFunc(self):
print('Do the work for buttonJob: < {} >'.format(self.buttonJob))
def main():
App = QApplication(sys.argv)
obj = WindowMDI()
title = 'PyQt5 QMainWindow'
obj.setWindowTitle(title)
obj.show()
sys.exit(App.exec())
if __name__ == '__main__':
main()
Re: Erweiterte Buttenbar
Verfasst: Donnerstag 19. Januar 2023, 18:15
von Axel-WAK
Stürzt schon ab beim Eingabefeld
Code: Alles auswählen
AttributeError: 'ButtonBar' object has no attribute 'buttonSearch'
Re: Erweiterte Buttenbar
Verfasst: Freitag 20. Januar 2023, 15:48
von Nobuddy
Ja, habe ich behoben, hier nochmals das Neuste.
Code: Alles auswählen
import sys
from PyQt5.QtCore import (
Qt,
)
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QMdiArea,
QComboBox,
QGridLayout,
QLineEdit,
QTextEdit,
QPushButton,
QToolBar,
QWidget,
)
from PyQt5.QtGui import (
QFont,
)
# Areas of buttonbar below
AREAS = {
'start' : ['search'],
'table' : ['search', 'back', 'next', 'new', 'delete'],
'replace' : ['search', 'search', 'find', 'replace', 'find all',
'replace all', 'text change back'],
}
class ButtonBar(QToolBar):
def __init__(self, area, parent=None):
super().__init__(parent=parent)
self.parent = parent
try:
className = parent.object.__class__.__name__
except AttributeError:
# not parent.object
try:
# if test
parent.test
className = True
except AttributeError:
className = False
self.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
fontSize = 14
parent.gridLayoutBarArea = QGridLayout()
func = parent.mainBarCallback
self.font = QFont('NimbusSansL', fontSize)
try:
self.buttonWidget
except AttributeError:
self.buttonWidget = dict()
y = 0
try:
names = AREAS[area]
except KeyError:
return
for x, name in enumerate(names):
self.addSeparator()
if name == 'search':
try:
s += 1
except UnboundLocalError:
s = 0
if s == 0:
# create cömbobox
selection = 'AUTO', 'COMBO', 'SEARCH', 'REPLACE'
parent.searchComboSelection = selection
self.cb = ComboBox(name, selection, self.comboChanged,
self.font, parent=self)
parent.gridLayoutBarArea.addWidget(QWidget(self.cb), y, x)
# create searchfield in toolbar
placeHolderText = 'Eingabefeld'
if s == 1:
placeHolderText = 'Suchfeld'
tF = TextField(name, placeHolderText, fontSize, parent=self)
parent.gridLayoutBarArea.addWidget(QWidget(tF), 0, x)
parent.buttonSearch()
self.addSeparator()
if name == 'search' and 'find' in AREAS[area]:
self.cb.setCurrentText('REPLACE')
continue
pb = PushButton(name, parent.gridLayoutBarArea, func, parent=self)
parent.gridLayoutBarArea.addWidget(QWidget(pb), y, x)
if not className:
self.cb.setEnabled(False)
tF.setReadOnly(True)
pb.setEnabled(False)
if (name == 'back' or name == 'next' or name == 'replace'
or name == 'replace all' or name == 'text change back'):
pb.setEnabled(False)
self.addSeparator()
self.setObjectName(area)
parent.buttonWidget = self.buttonWidget
def comboChanged(self, text):
print('comboChanged: ', text)
self.comboState = text
self.buttonWidget['searchCombo'].setCurrentText(text)
self.buttonWidget['searchField'].setText('')
self.buttonWidget['searchField'].setFocus()
self.parent.buttonBarCallback(text)
if text == 'COMBO' or text == 'AUTO':
self.parent.buttonCombo()
elif text == 'REPLACE':
print('+++++++++++++++++++++++++++++++++')
def searchFieldCallback(self, text):
print('searchFieldCallback', text)
# state to combobox
state = self.buttonWidget['searchCombo'].currentText()
# get text to search field
if state == 'COMBO':
text = text.upper()
self.focusWidget().setText(text)
self.focusWidget().setFocus()
self.parent.buttonSearch()
class ComboBox(QComboBox):
def __init__(self, name, selection, func, font, parent=None):
super().__init__(parent=parent)
self.setEnabled(True)
objectName = '{}Combo'.format(name.lower())
self.setObjectName(objectName)
comboState = 'AUTO'
self.setCurrentText(comboState)
[self.addItem(name) for name in selection]
self.comboState = self.currentText()
self.activated[str].connect(func)
self.setFont(font)
parent.buttonWidget = {'searchCombo' : self}
parent.buttonWidget[objectName] = self
parent.addWidget(self)
class TextField(QLineEdit):
def __init__(self, name, placeHolderText, fontSize, parent=None):
super().__init__(parent=parent)
self.parent = parent
objectName = '{}Field'.format(name.lower())
if placeHolderText == 'Suchfeld':
objectName = 'replaceField'
placeHolderText = 'Ersatztext'
self.setObjectName(objectName)
self.setPlaceholderText(placeHolderText)
f = self.font() # lineedit current font
f.setPointSize(fontSize) # change it's size
self.setFont(f) # set font
self.setFocusPolicy(Qt.StrongFocus)
self.resize(200,40)
self.setMaximumWidth(400)
self.setMinimumHeight(40)
self.setReadOnly(False) # True / False (write)
self.installEventFilter(parent)
self.textChanged[str].connect(parent.searchFieldCallback)
parent.buttonWidget[objectName] = self
parent.addWidget(self)
class PushButton(QPushButton):
def __init__(self, name, layout, func, parent=None):
super().__init__(parent=parent)
objectName = name.lower()
self.setObjectName(objectName)
self.setText(name.capitalize())
self.clicked.connect(func)
self.setLayout(layout)
self.setCheckable(False) # True / False
self.setEnabled(True)
self.setFont(parent.font)
try:
parent.buttonWidget[name] = self
except AttributeError:
parent.buttonWidget = {name : self}
parent.buttonWidget[name] = self
parent.addWidget(self)
class WindowMDI(QMainWindow):
def __init__(self):
super().__init__()
self.mdi = QMdiArea()
# set geomerty
self.setGeometry(100, 300, 1000, 500)
# toolbar below
self.test = True
self.buttonArea = ButtonBar('start', parent=self)
self.addToolBar(Qt.BottomToolBarArea, self.buttonArea)
self.buttonBarMemory = dict()
self.toolBarMemory = dict()
# attribute for messagebox
self.resultMB = QTextEdit()
self.resultMB.setPlainText('False')
self.setCentralWidget(self.mdi)
def buttonCombo(self):
print('buttonSearch')
def buttonBarCallback(self, name):
print('buttonBarCallback: ', name)
if name == 'COMBO':
return
print('objectName: ', self.buttonArea.objectName())
self.buttonArea.setParent(None)
self.buttonArea.deleteLater()
self.buttonArea.close()
self.searchBar = False
self.replaceBar = False
if name == 'REPLACE':
self.replaceBar = True
area = name.lower()
else:
self.searchBar = True
area = 'start'
self.buttonArea = ButtonBar(area, parent=self)
self.addToolBar(Qt.BottomToolBarArea, self.buttonArea)
#@pyqtSlot()
def mainBarCallback(self):
self.buttonJob = self.sender().text().lower()
print('Do the work for buttonJob: < {} >'.format(self.buttonJob))
def buttonSearch(self):
print('buttonSearch')
def main():
App = QApplication(sys.argv)
obj = WindowMDI()
title = 'PyQt5 QMainWindow'
obj.setWindowTitle(title)
obj.show()
sys.exit(App.exec())
if __name__ == '__main__':
main()
Re: Erweiterte Buttenbar
Verfasst: Freitag 20. Januar 2023, 16:01
von __deets__
Ui. Das sieht sehr problematisch aus. Diese ganze attribut-getterei, und className ist True/False, statt ein Name zu sein (oder vielleicht None), und ganz generell ist es ein riesen Entwurfsproblem, wenn ein Kind-Widget sich so viel Wissen ueber die Widgets ueber im durch die parent-relation aufsammelt. Auch einen UnboundLocalError faengt man *niemals* ab - das ist drumrumarbeiten um einen Programmierfehler!
Re: Erweiterte Buttenbar
Verfasst: Freitag 20. Januar 2023, 16:42
von Nobuddy
Ja, da habe ich wohl noch einiges zu lernen.
Die Classen "ComboBox, TextField, PushButton" habe ich aus ButtonBar herausgenommen, da ich diese auch für andere Aufgaben verwenden möchte.
Bei mir, ist der Weg das Ziel
Vielleicht kannst Du mir Beispiele zeigen, wie es besser geht?
Re: Erweiterte Buttenbar
Verfasst: Freitag 20. Januar 2023, 18:09
von Axel-WAK
Nobuddy hat geschrieben: Freitag 20. Januar 2023, 16:42
Bei mir, ist der Weg das Ziel
Aber was ist das Ziel? Was soll es am Ende werden? Ein Texteditor mit Suchen/Ersetzen ?
Re: Erweiterte Buttenbar
Verfasst: Freitag 20. Januar 2023, 18:37
von Nobuddy
Nein, bin Rentner und interesiere mich für Python und Qt.
Das, was hier mein Ziel war, die untere Buttonbar, nach verschiedenen Anforderungen zu gestalten.
Ich habe ein Hauptfenster MDI, aus dem ich auf Dateien zugreifen und öffnen kann. Textdateien und Tabellen, werden im MDI angezeigt.
Bei Textdateien gibt es viele Möglichkeiten, diese zu bearbeiten. Hatte mir überlegt, Text zu durchsuchen und Teile ersetzen zu können, daher auch bei der ComboBox Auswahl "REPLACE", die eine neue Buttonbar anbietet.
Ich habe das in meinem MDI integriert und bin weiter am Optimieren.
