It seems by default the Tab method for changing focus through widgets only stops once in a QButtonGroup and one is expected to move inside the group with the arrow keys (which only works with radio buttons, anyway). I want, however, to create a button group with QCheckBox inside, with the "exclusive" behaviour but allowing to uncheck all boxes, and where I can use the Tab key to move normally, as if they were not in a group.
The "clearable" part I could get it done with a subclass, but for the tabbing, it seems as soon as a button in the group gets the focus, it changes the focusPolicy for all other buttons such that they don't accept Tab (from 11 to 10), while the button that got the focus changes to 11. How can I disable/override this? Who is messing with the focus policies? I've tried defining a focusInEvent method for a QCheckBox, and I see that it changes "this button's" focusPolicy, but how can I know, from "this button" what the "other buttons" are (given that the final application may have many button groups)? Ideally, I would do something to the QButtonGroup subclass, but I don't know if it has any method that can respond to a focus change in its buttons.
Here is a small example. The "Tab order" button prints the current tab order and focus policies:
#!/usr/bin/env python3
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QSize
class Custom(QWidget):
def __init__(self, text1, text2):
QWidget.__init__(self)
self.box = QCheckBox(text1)
self.button = QPushButton(text2)
layout = QHBoxLayout()
layout.addWidget(self.box)
layout.addWidget(self.button)
self.setLayout(layout)
self._text = f'{text1} {text2}'
self.setFocusPolicy(QtCore.Qt.ClickFocus)
def text(self):
return self._text
class ClearableButtonGroup(QButtonGroup):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.button = None
def addButton(self, button):
try:
super().addButton(button)
button.pressed.connect(self.button_pressed)
button.clicked.connect(self.button_clicked)
except TypeError:
pass
def removeButton(self, button):
try:
button.pressed.disconnect(self.button_pressed)
button.clicked.disconnect(self.button_clicked)
super().removeButton(button)
except AttributeError:
pass
def button_pressed(self):
if (self.sender() is self.checkedButton()):
self.button = self.sender()
else:
self.button = None
def button_clicked(self):
button = self.sender()
if (button is self.button):
exclusive = self.exclusive()
self.setExclusive(False)
button.setChecked(False)
self.setExclusive(exclusive)
class HelloWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
centralWidget = QWidget(self)
self.setCentralWidget(centralWidget)
gridLayout = QGridLayout(centralWidget)
self.box1 = Custom('Box 1', 'Button 1')
self.box2 = Custom('Box 2', 'Button 2')
self.box3 = Custom('Box 3', 'Button 3')
self.box4 = Custom('Box 4', 'Button 4')
gridLayout.addWidget(self.box1, 0, 0)
gridLayout.addWidget(self.box2, 1, 0)
gridLayout.addWidget(self.box3, 2, 0)
gridLayout.addWidget(self.box4, 3, 0)
button1 = QPushButton('Tab order')
gridLayout.addWidget(button1, 4, 1)
button1.clicked.connect(self.tab)
group = ClearableButtonGroup(self)
group.setExclusive(True)
group.addButton(self.box1.box)
group.addButton(self.box2.box)
group.addButton(self.box3.box)
group.addButton(self.box4.box)
def tab(self):
print_tab_order(self)
def print_tab_order(widget):
w = widget
while True:
try:
print('Text: {}; FocusPolicy: {}'.format(w.text(), w.focusPolicy()))
except AttributeError:
pass
w = w.nextInFocusChain()
if w == widget:
break
print('----')
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = HelloWindow()
mainWin.show()
sys.exit( app.exec_() )
It seems that this behavior is missing, if the QAbstractButton source code is revised it is implemented:
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qabstractbutton.cpp?h=5.14#n1088
void QAbstractButton::keyPressEvent(QKeyEvent *e)
{
// ...
d->moveFocus(e->key());
// ...
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qabstractbutton.cpp?h=5.14#n247
void QAbstractButtonPrivate::moveFocus(int key)
{
// ...
if (candidate) {
if (key == Qt::Key_Up || key == Qt::Key_Left)
candidate->setFocus(Qt::BacktabFocusReason);
else
candidate->setFocus(Qt::TabFocusReason);
}
}
As it is observed, all the buttons are considered as a unit and there is no way to disable it, so a workaround is to implement a class that has the same functionality, and in a previous post I implemented it which in your case is:
class ButtonManager(QtCore.QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._buttons = []
#property
def buttons(self):
return self._buttons
def add_button(self, button):
if isinstance(button, QtWidgets.QAbstractButton):
button.toggled.connect(self.on_toggled)
self.buttons.append(button)
#QtCore.pyqtSlot(bool)
def on_toggled(self, state):
button = self.sender()
if state:
for b in self.buttons:
if b != button and b.isChecked():
b.blockSignals(True)
b.setChecked(False)
b.blockSignals(False)
else:
button.blockSignals(True)
button.setChecked(False)
button.blockSignals(False)
# ...
button1.clicked.connect(self.tab)
button = ButtonManager(self)
button.add_button(self.box1.box)
button.add_button(self.box2.box)
button.add_button(self.box3.box)
button.add_button(self.box4.box)
# ...
Related
I have a QMainWindow, inside there is a QMenu, QLineEdit, and one QPushButton.
Every time I click the button, it plays a sound and then adds a text to the QLineEdit.
In my QMenu the user must be able to choose which sound plays by checking it.
I tried to achieve this by changing a variable self.s inside the MainWindow class every time a QAction is checked, meanwhile, the other QAction's are unchecked. So in my playsound() I just put the self.view.s as the argument.
But it seems that it's only reading the original self.view.s, which is the first sound. My signals to change self.view.s does not work. Also, the other QActions aren't unchecked as I wanted them to.
Below is my code:
import sys
from functools import partial
from playsound import playsound
from threading import Thread
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.buttons = {}
self.setWindowTitle("Try")
central_widget = QWidget()
self.setCentralWidget(central_widget)
self.lay = QVBoxLayout(central_widget)
self.lineedit()
button = {"HEY! ": (0, 0, 0, 0)}
page = QWidget()
layout = QGridLayout(page)
for btnText, pos in button.items():
self.buttons[btnText] = QPushButton(btnText)
layout.addWidget(self.buttons[btnText], *pos)
self.lay.addWidget(page)
self.music()
def music(self):
self.s = 'sound1.mp3'
self.x = 'sound1.mp3'
self.y = 'sound2.mp3'
self.z = 'disable.mp3'
def lineedit(self):
self.le = QLineEdit()
self.le.setFixedHeight(35)
self.lay.addWidget(self.le)
def set_lineedit(self, text):
self.le.setText(text)
self.le.setFocus()
def line(self):
return self.le.text()
class Menu:
def __init__(self, MainWindow):
super().__init__()
self.view = MainWindow
self.menuBar()
#self.actionSignals()
def menuBar(self):
self.menuBar = QMenuBar()
self.view.setMenuBar(self.menuBar)
self.menu = QMenu(self.menuBar)
self.menu.setTitle('Menu')
self.sounds = QMenu(self.menu)
self.sounds.setTitle('Select Sound')
self.sound1 = QAction(self.menuBar)
self.sound2 = QAction(self.menuBar)
self.disable = QAction(self.menuBar)
self.mute = QAction(self.menuBar)
self.mute.setText('Mute Background')
self.mute.setCheckable(True)
self.mute.setChecked(False)
self.sound1.setText('Sound 1')
self.sound1.setCheckable(True)
self.sound1.setChecked(True)
self.sound2.setText('Sound 2')
self.sound2.setCheckable(True)
self.sound2.setChecked(False)
self.disable.setText('Disable Sound')
self.disable.setCheckable(True)
self.disable.setChecked(False)
self.sounds.addAction(self.sound1)
self.sounds.addAction(self.sound2)
self.sounds.addAction(self.disable)
self.menuBar.addAction(self.menu.menuAction())
self.menu.addAction(self.mute)
self.menu.addAction(self.sounds.menuAction())
def menu_signals(self):
self.sound1.triggered.connect(self.sound_1)
self.sound2.triggered.connect(self.sound_2)
self.disable.triggered.connect(self.disabled)
def sound_1(self, checked):
if checked:
self.sound2.setChecked(False)
self.disable.setChecked(False)
self.view.s = self.view.x
else:
self.sound1.setChecked(True)
def sound_2(self, checked):
if checked:
self.sound1.setChecked(False)
self.disable.setChecked(False)
self.view.s = self.view.y
else:
self.sound2.setChecked(True)
def disabled(self, checked):
if checked:
self.sound2.setChecked(False)
self.sound1.setChecked(False)
self.view.s = self.view.z
else:
self.sound1.setChecked(True)
class Controller:
def __init__(self, MainWindow):
self.view = MainWindow
self.connectSignals()
def background(self):
while True:
playsound('background.mp3')
def playsound(self):
playsound(self.view.s, False)
def buildExpression(self, sub_exp):
expression = self.view.line() + sub_exp
self.view.set_lineedit(expression)
def connectSignals(self):
for btnText, btn in self.view.buttons.items():
self.view.buttons[btnText].clicked.connect(self.playsound)
self.view.buttons[btnText].clicked.connect(partial(self.buildExpression, btnText))
app = QApplication(sys.argv)
w = MainWindow()
x = Controller(w)
Thread(target = x.background, daemon = True).start()
m = Menu(w)
w.show()
app.exec()
I want to be able to change the value within playsound() depending on which QAction is checked in the Menu Bar. While one QAction is checked, the other QAction's should be unchecked.
This is where an action group comes into play. QActionGroup allows for mutually exclusive actions. It also provides convenient access to the selected action through the checkedAction method.
Create a QActionGroup object (e.g. self.soundGroup = QActionGroup(self))
Create your actions with the group as parent (e.g. self.sound1 = QAction(self.soundGroup))
For each of your actions, set their corresponding sound as their data, e.g. self.sound1.setData('sound1.mp3')
Ensure the action group is exclusive (I believe it's the default, but you may use self.soundGroup.setExclusive(True))
Use self.soundGroup.checkedAction() to get the checked action (selected sound) instead of self.view.s: playsound(self.soundGroup.checkedAction().data(), False)
You do not need any of your wiring between the actions and updates to self.view.s anymore. Just remove all of that.
I have the following code to create a QTreeWidget and a contextmenu with 2 actions.
import sys
from PyQt5 import QtCore, QtWidgets
class Dialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__()
self.tw = QtWidgets.QTreeWidget()
self.tw.setHeaderLabels(['Name', 'Cost ($)'])
cg = QtWidgets.QTreeWidgetItem(['carrots', '0.99'])
c1 = QtWidgets.QTreeWidgetItem(['carrot', '0.33'])
self.tw.addTopLevelItem(cg)
self.tw.addTopLevelItem(c1)
self.tw.installEventFilter(self)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.tw)
def eventFilter(self, source: QtWidgets.QTreeWidget, event):
if (event.type() == QtCore.QEvent.ContextMenu and
source is self.tw):
menu = QtWidgets.QMenu()
AAction = QtWidgets.QAction("AAAAA")
AAction.triggered.connect(lambda :self.a(source.itemAt(event.pos())))
BAction = QtWidgets.QAction("BBBBBB")
BAction.triggered.connect(lambda :self.b(source, event))
menu.addAction(AAction)
menu.addAction(BAction)
menu.exec_(event.globalPos())
return True
return super(Dialog, self).eventFilter(source, event)
def a(self, item):
if item is None:
return
print("A: {}".format([item.text(i) for i in range(self.tw.columnCount())]))
def b(self, source, event):
item = source.itemAt(event.pos())
if item is None:
return
print("B: {}".format([item.text(i) for i in range(source.columnCount())]))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Dialog()
window.setGeometry(600, 100, 300, 200)
window.show()
sys.exit(app.exec_())
When opening the contextmenu in the header and clicking on one of the actions it prints either carrot or carrots, depending on where in the contextmenu I click. But I give the position of right click event to the functions.
So why is this happening and what can I do to stop it?
Your code has 2 errors:
The main error is that the itemAt() method uses the coordinates with respect to the viewport() and not with respect to the view (the QTreeWidget) so you will get incorrect items (the header occupies a space making the positions with respect to the QTreeWidget and the viewport() have an offset).
You should not block the eventloop, for example blocking the eventFilter you may be blocking other events that would cause errors that are difficult to debug, in this case it is better to use a signal.
class Dialog(QtWidgets.QDialog):
rightClicked = QtCore.pyqtSignal(QtCore.QPoint)
def __init__(self, parent=None):
super(Dialog, self).__init__()
self.tw = QtWidgets.QTreeWidget()
self.tw.setHeaderLabels(["Name", "Cost ($)"])
cg = QtWidgets.QTreeWidgetItem(["carrots", "0.99"])
c1 = QtWidgets.QTreeWidgetItem(["carrot", "0.33"])
self.tw.addTopLevelItem(cg)
self.tw.addTopLevelItem(c1)
self.tw.viewport().installEventFilter(self)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.tw)
self.rightClicked.connect(self.handle_rightClicked)
def eventFilter(self, source: QtWidgets.QTreeWidget, event):
if event.type() == QtCore.QEvent.ContextMenu and source is self.tw.viewport():
self.rightClicked.emit(event.pos())
return True
return super(Dialog, self).eventFilter(source, event)
def handle_rightClicked(self, pos):
item = self.tw.itemAt(pos)
if item is None:
return
menu = QtWidgets.QMenu()
print_action = QtWidgets.QAction("Print")
print_action.triggered.connect(lambda checked, item=item: self.print_item(item))
menu.addAction(print_action)
menu.exec_(self.tw.viewport().mapToGlobal(pos))
def print_item(self, item):
if item is None:
return
texts = []
for i in range(item.columnCount()):
text = item.text(i)
texts.append(text)
print("B: {}".format(",".join(texts)))
Although it is unnecessary that you use an eventFilter to handle the contextmenu since a simpler solution is to set the contextMenuPolicy of the QTreeWidget to Qt::CustomContextMenu and use the customContextMenuRequested signal:
class Dialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__()
self.tw = QtWidgets.QTreeWidget()
self.tw.setHeaderLabels(["Name", "Cost ($)"])
cg = QtWidgets.QTreeWidgetItem(["carrots", "0.99"])
c1 = QtWidgets.QTreeWidgetItem(["carrot", "0.33"])
self.tw.addTopLevelItem(cg)
self.tw.addTopLevelItem(c1)
self.tw.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.tw.customContextMenuRequested.connect(self.handle_rightClicked)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.tw)
def handle_rightClicked(self, pos):
item = self.tw.itemAt(pos)
if item is None:
return
menu = QtWidgets.QMenu()
print_action = QtWidgets.QAction("Print")
print_action.triggered.connect(lambda checked, item=item: self.print_item(item))
menu.addAction(print_action)
menu.exec_(self.tw.viewport().mapToGlobal(pos))
def print_item(self, item):
if item is None:
return
texts = []
for i in range(item.columnCount()):
text = item.text(i)
texts.append(text)
print("B: {}".format(",".join(texts)))
I made this code, but it returns the previous value.
Code:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class LoginForm(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Test')
layout = QGridLayout()
choices = ['1', '2', '3']
btHome = QPushButton('Button',self)
btHome.clicked.connect(self.callback)
self.CmbBx_Cod = QComboBox()
self.CmbBx_Cod.addItem('Select a value')
for choices in choices:
self.CmbBx_Cod.addItem(choices)
self.CmbBx_Cod.view().pressed.connect(self.callback)
layout.addWidget(btHome, 0, 0)
layout.addWidget(self.CmbBx_Cod, 0, 2)
self.setLayout(layout)
def callback(self):
code = self.CmbBx_Cod.currentText()
print(f'code {code} selected!')
if __name__ == '__main__':
app = QApplication(sys.argv)
form = LoginForm()
form.show()
sys.exit(app.exec())
When I click the button I have the value I want, but I wanted it when I selected a code. Is there any other method of doing this?
Explanation
In the first place, it should be understood that the pressed signal is emitted as soon as the mouse is placed with the button pressed on an item, but that is not used by the QComboBox to update the current text, but rather for stability the clicked signal that is emitted when the mouse is released, so in your logic you are trying to get the current text before it is updated so you get that unexpected behavior.
Proper solution
If you want to get the item pressed then you should not use the QComboBox but directly the QModelIndex sent in the signal:
def callback(self, index):
code = index.data()
print(f'code {code} selected!')
If instead you want to get the displayed text after releasing the mouse then you can use the clicked signal of the view, or better the currentTextChanged or currentIndexChanged signal.
class LoginForm(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test")
layout = QGridLayout()
choices = ["1", "2", "3"]
btHome = QPushButton("Button", self)
btHome.clicked.connect(self.callback)
self.CmbBx_Cod = QComboBox()
self.CmbBx_Cod.addItem("Select a value")
for choices in choices:
self.CmbBx_Cod.addItem(choices)
self.CmbBx_Cod.currentTextChanged.connect(self.callback)
layout.addWidget(btHome, 0, 0)
layout.addWidget(self.CmbBx_Cod, 0, 2)
self.setLayout(layout)
def callback(self, code):
print(f"code {code} selected!")
If you want to get the current text by pressing the button then you must create another slot:
class LoginForm(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test")
layout = QGridLayout()
choices = ["1", "2", "3"]
btHome = QPushButton("Button", self)
btHome.clicked.connect(self.button_callback)
self.CmbBx_Cod = QComboBox()
self.CmbBx_Cod.addItem("Select a value")
for choices in choices:
self.CmbBx_Cod.addItem(choices)
self.CmbBx_Cod.currentTextChanged.connect(self.combo_callback)
layout.addWidget(btHome, 0, 0)
layout.addWidget(self.CmbBx_Cod, 0, 2)
self.setLayout(layout)
def button_callback(self):
self.printer(self.CmbBx_Cod.currentText())
def combo_callback(self, code):
self.printer(code)
def printer(self, code):
print(f"code {code} selected!")
I'm attempting to create a Login System type dialog box for practice using PyQt5 (I'm quite new to the module) and i'm trying to give the user the ability to click (Ok, Cancel, Apply) as the buttons underneath inputs boxes for Username / Password, but i'm not sure how I can actually get the apply button to work. I have buttons.accepted.connect(*method*) and buttons.rejected.connect(*method*) but I don't know how to specify the pressing of the accept button. I have tried using buttons.clicked(dlgButtons[0] (Which is where the button is stored) but it just gives me an error.
The code below is my declaration of the buttons if that helps. Thanks
buttons = qt.QDialogButtonBox()
dlgButtons = (qt.QDialogButtonBox.Apply, qt.QDialogButtonBox.Ok, qt.QDialogButtonBox.Cancel)
buttons.setStandardButtons(
dlgButtons[0] | dlgButtons[1] | dlgButtons[2]
)
One possible solution might look like this:
from PyQt5.QtWidgets import *
class ModelessDialog(QDialog):
def __init__(self, part, threshold, parent=None):
super().__init__(parent)
self.setWindowTitle("Baseline")
self.setGeometry(800, 275, 300, 200)
self.part = part
self.threshold = threshold
self.threshNew = 4.4
label = QLabel("Part : {}\nThreshold : {}".format(
self.part, self.threshold))
self.label2 = QLabel("ThreshNew : {:,.2f}".format(self.threshNew))
self.spinBox = QDoubleSpinBox()
self.spinBox.setMinimum(-2.3)
self.spinBox.setMaximum(99)
self.spinBox.setValue(self.threshNew)
self.spinBox.setSingleStep(0.02)
self.spinBox.valueChanged.connect(self.valueChang)
buttonBox = QDialogButtonBox(
QDialogButtonBox.Ok
| QDialogButtonBox.Cancel
| QDialogButtonBox.Apply)
layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(self.label2)
layout.addWidget(self.spinBox)
layout.addWidget(buttonBox)
self.resize(300, 200)
self.setLayout(layout)
okBtn = buttonBox.button(QDialogButtonBox.Ok)
okBtn.clicked.connect(self._okBtn)
cancelBtn = buttonBox.button(QDialogButtonBox.Cancel)
cancelBtn.clicked.connect(self.reject)
applyBtn = buttonBox.button(QDialogButtonBox.Apply) # +++
applyBtn.clicked.connect(self._apply) # +++
def _apply(self): # +++
print('Hello Apply')
def _okBtn(self):
print("""
Part : {}
Threshold : {}
ThreshNew : {:,.2f}""".format(
self.part, self.threshold, self.spinBox.value()))
def valueChang(self):
self.label2.setText("ThreshNew : {:,.2f}".format(self.spinBox.value()))
class Window(QWidget):
def __init__(self):
super().__init__()
label = QLabel('Hello Dialog', self)
button = QPushButton('Open Dialog', self)
button.clicked.connect(self.showDialog)
layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(button)
self.setLayout(layout)
def showDialog(self):
self.dialog = ModelessDialog(2, 55.77, self)
self.dialog.show()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
win = Window()
win.resize(300, 200)
win.show()
sys.exit(app.exec_())
What you are storing in the dlgButtons is just a list of enums, specifically the StandardButton enum, which is a list of identifiers for the buttons, they are not the "actual" buttons.
Also, you cannot use the clicked signal like this:
buttons.clicked(dlgButtons[0])
That will generate a crash, as signals are not callable. The argument of the clicked() signal is what will be received from the slot, which means that if you connect a function to that signal, the function will receive the clicked button:
buttons.clicked.connect(self.buttonsClicked)
def buttonsClicked(self, button):
print(button.text())
The above will print the text of the clicked button (Ok, Apply, Cancel, or their equivalent localized text).
What you're looking for is to connect to the clicked signals of the actual buttons, and you can get the individual reference to each button by using the button() function:
applyButton = buttons.button(qt.QDialogButtonBox.Apply)
applyButton.clicked.connect(self.applyFunction)
In particular I have 2 questions:
1) How can I remove those thin lines between the widgets? setMargin(0) and setSpacing(0)
are already set.
2) In a further step I want to remove the window title bar with FramelessWindowHint.
To drag the window, I'll bind a mouseevent on the upper dark yellow widget. Right now, the upper widget is a QTextEdit with suppressed keyboard interactions. For the draging purpose, I doubt this widget is good... So the question is, what other widgets are good to create a colored handle to drag the window? Perhaps QLabel?
EDIT: Here is the code. I only used QTestEdit-Widgets.
from PyQt4.QtGui import *
from PyQt4 import QtGui,QtCore
import sys
class Note(QWidget):
def __init__(self, parent = None):
super(QWidget, self).__init__(parent)
self.createLayout()
self.setWindowTitle("Note")
def createLayout(self):
textedit = QTextEdit()
grip = QTextEdit()
grip.setMaximumHeight(16) #reduces the upper text widget to a height to look like a grip of a note
grip.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) #suppresses the scroll bar that appears under a certain height
empty = QTextEdit()
empty.setMaximumHeight(16)
empty.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
resize = QTextEdit()
resize.setMaximumHeight(16)
resize.setMaximumWidth(16)
resize.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
layout = QVBoxLayout()
layout.addWidget(grip)
layout.addWidget(textedit)
layout.setMargin(0)
layout.setSpacing(0)
layoutBottom=QHBoxLayout()
layoutBottom.addWidget(empty)
layoutBottom.addWidget(resize)
layout.addLayout(layoutBottom)
self.setLayout(layout)
# Set Font
textedit.setFont(QFont("Arial",16))
# Set Color
pal=QtGui.QPalette()
rgb=QtGui.QColor(232,223,80) #Textwidget BG = yellow
pal.setColor(QtGui.QPalette.Base,rgb)
textc=QtGui.QColor(0,0,0)
pal.setColor(QtGui.QPalette.Text,textc)
textedit.setPalette(pal)
empty.setPalette(pal)
pal_grip=QtGui.QPalette()
rgb_grip = QtGui.QColor(217,207,45)
pal_grip.setColor(QtGui.QPalette.Base,rgb_grip)
textc_grip=QtGui.QColor(0,0,0)
pal.setColor(QtGui.QPalette.Text,textc_grip)
grip.setPalette(pal_grip)
resize.setPalette(pal_grip)
resize.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
empty.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
grip.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
#textedit.setTextInteractionFlags(QtCore.Qt.NoTextInteraction) #total text widget lock
#textedit.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse) #Lock?
#http://qt-project.org/doc/qt-4.8/qt.html#TextInteractionFlag-enum
#self.setWindowFlags(QtCore.Qt.FramelessWindowHint) #removes the title bar
#self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) #to make the window stay on top
class Main():
def __init__(self):
self.notes=[]
self.app = QApplication(sys.argv)
self.app.setQuitOnLastWindowClosed(False);
self.trayIcon = QSystemTrayIcon(QIcon(r"C:\Users\Thomas\Desktop\SimpleNotes.ico"), self.app)
self.menu = QMenu()
self.newWindow = self.menu.addAction("New note")
self.separator = self.menu.addSeparator()
self.hideNotes = self.menu.addAction("Hide all notes")
self.showNotes = self.menu.addAction("Show all notes")
self.separator = self.menu.addSeparator()
self.saveNotes = self.menu.addAction("Save notes")
self.loadNotes = self.menu.addAction("Load notes")
self.separator = self.menu.addSeparator()
self.showHelp = self.menu.addAction("Show help")
self.showAbout = self.menu.addAction("Show about")
self.separator = self.menu.addSeparator()
self.exitAction = self.menu.addAction("Quit notes")
self.exitAction.triggered.connect(self.close)
self.newWindow.triggered.connect(self.newNote)
self.trayIcon.setContextMenu(self.menu)
self.trayIcon.show()
self.app.exec()
def newNote(self):
print("Create new note entry has been clicked")
note=Note()
note.show()
self.notes.append(note)
print(self.notes)
def hideNotes(self):
pass
def showNotes(self):
pass
def saveNotes(self):
pass
def loadNotes(self):
pass
def showHelp(self):
pass
def showAbout(self):
pass
def close(self):
self.trayIcon.hide()
self.app.exit()
print("Exit menu entry has been clicked")
if __name__ == '__main__':
Main()
The answer from thuga was good enough, so i post it here:
textedit.setFrameShape(QtGui.QFrame.NoFrame)
and
grip.setFrameShape(QtGui.QFrame.NoFrame)
made the line disappear.
for 1. I've used:
textEdit.setFrameStyle(QtGui.QFrame.NoFrame)
ui->fr200->setFrameShape(QFrame::NoFrame);
ui->fr201->setFrameShape(QFrame::NoFrame);
ui->fr202->setFrameShape(QFrame::NoFrame);
ui->fr203->setFrameShape(QFrame::NoFrame);
ui->fr204->setFrameShape(QFrame::NoFrame);
ui->fr205->setFrameShape(QFrame::NoFrame);
ui->fr206->setFrameShape(QFrame::NoFrame);
ui->fr207->setFrameShape(QFrame::NoFrame);
ui->fr208->setFrameShape(QFrame::NoFrame);