I've a Dialog window with some QLineEdits to insert the data in my software, I Switch from first QLineEdit to the next with TAB key on keyboard
I want the background to change its color to (for example) Yellow and when is focused out (the focus is switched to another) it must go back to White a QLineEdit is Focused,the . for doing this, I inserted a Different StyleSheet in FocusInEvent and FocusOutEvent.
But i have a problem...
The Problem is When i focus on QlineEdit it works (The background change color to yellow) but if i write something and i switch to the next QLineEdit. the TextCursor in the last QlineEdit doesn't disappear and I view two or also more Text Cursors in my window.
*I omit part of source code (Like=>Layout, Database Functions, etc..) because I think they are irrelevant for helping me to fix my problem.
from PyQt4 import QtGui,QtCore;
class AddWindow(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self);
#Surname
self.SurnameLabel=QtGui.QLabel("Surname:",self);
self.SurnameLabel.move(5,20);
self.SurnameBox=QtGui.QLineEdit(self);
self.SurnameBox.move(5,35);
self.SurnameBox.focusInEvent=self.OnSurnameBoxFocusIn;
self.SurnameBox.focusOutEvent=self.OnSurnameBoxFocusOut;
#Name
self.NameLabel=QtGui.QLabel("Name:",self);
self.NameLabel.move(150,20);
self.NameBox=QtGui.QLineEdit(self);
self.NameBox.move(150,35);
self.NameBox.focusInEvent=self.OnNameBoxFocusIn;
self.NameBox.focusOutEvent=self.OnNameBoxFocusOut;
def OnSurnameBoxFocusIn(self,event):
self.SurnameBox.setStyleSheet("QLineEdit {background-color:yellow}");
def OnSurnameBoxFocusOut(self,event):
self.SurnameBox.setStyleSheet("QLineEdit {background-color:white}");
def OnNameBoxFocusIn(self,event):
self.NameBox.setStyleSheet("QLineEdit {background-color:yellow}");
def OnNameBoxFocusOut(self,event):
self.NameBox.setStyleSheet("QLineEdit {background-color:white}");
The problem is your implement some event is important of cursor behavior and your code has been interrupt it. To fix it please get old behavior back them after your code has work successful;
def OnSurnameBoxFocusIn(self,event):
self.SurnameBox.setStyleSheet("QLineEdit {background-color:yellow}");
QtGui.QLineEdit.focusInEvent(self.SurnameBox,event) # <- put back old behavior
def OnSurnameBoxFocusOut(self,event):
self.SurnameBox.setStyleSheet("QLineEdit {background-color:white}");
QtGui.QLineEdit.focusOutEvent(self.SurnameBox,event) # <- put back old behavior
def OnNameBoxFocusIn(self,event):
self.NameBox.setStyleSheet("QLineEdit {background-color:yellow}");
QtGui.QLineEdit.focusInEvent(self.NameBox,event) # <- put back old behavior
def OnNameBoxFocusOut(self,event):
self.NameBox.setStyleSheet("QLineEdit {background-color:white}");
QtGui.QLineEdit.focusOutEvent(self.NameBox,event) # <- put back old behavior
Regards,
Related
This question already has an answer here:
adjust size after child widget resized in Qt
(1 answer)
Closed 2 years ago.
I have a QDialog containing a QTabWidget, whose tabs vary in size. Following these instructions, which are similar to another stack overflow answer, I have the following code (self.tabs is a dictionary of the tab widgets):
class Panel(NXDialog):
def __init__(self, panel, parent=None):
super(Panel, self).__init__(parent)
self.tabwidget = QtWidgets.QTabWidget()
self.tabwidget.currentChanged.connect(self.update)
...
#property
def tab(self):
return self.tabwidget.currentWidget()
def update(self):
if self.tabwidget.count() == 0:
self.setVisible(False)
else:
for tab in [tab for tab in self.tabs if tab is not self.tab]:
try:
self.tabs[tab].setSizePolicy(QtWidgets.QSizePolicy.Ignored,
QtWidgets.QSizePolicy.Ignored)
self.tabs[tab].update()
except Exception:
pass
self.tab.setSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Preferred)
self.tab.update()
self.adjustSize()
When I add a new tab, this works very well. The tab does resize as I want. However, subsequent changes in the tab selection have no effect, even though my debugger confirms that this update function is called.
My application has an embedded shell that shares a namespace with the GUI so I can address all the PyQt widgets. If I call tab.adjustSize() in the shell, where tab points to the selected tab, the tab does resize! So my question is why the adjustSize function is ignored when I make the selection and trigger the currentChanged signal using the GUI, but is not ignored when I call the same slot function a little later from a shell. I've tried adding a sleep time and recursively cycling through the parent widgets calling adjustSize for each of them, but it has no effect. I've also tried adding self.repaint() as well as programmatically changing focus and back again, but nothing works except typing it from the shell.
I'm running PyQt5 v5.12.5 on Python 3.8 but I get the same behavior with PyQt v5.9.
Another stackoverflow question has helped me solve the problem. It seems that the previous changes in SizePolicy might still have been waiting in the GUI event loop. Clearing the loop first ensures that the adjustSize works.
This is all that is needed.
QtWidgets.QApplication.instance().processEvents()
self.adjustSize()
I confess I'm surprised this issue hasn't come up for me before, but I hope it's helpful to anyone else with the same issue.
I have 2 different QListwidgets which scrolls are synced properly with the code below. The problem is the secondary Qlistwidget (the one that is following the other´s scroll) doesn´t update its items unless i hover over it with the mouse.
I have very little experience with pyqt, so the only thing i tried is using the repaint and update methods (i added both in the code, at the end of the function). Unfortunately nothing really happens.
def move_scrollbar(vs, value):
vs.blockSignals(True)
vs.setValue(value)
vs.blockSignals(False)
self.list1.repaint()
self.list2.repaint()
self.list1.update()
self.list2.update()
vs1 = self.list1.verticalScrollBar()
vs2 = self.list2.verticalScrollBar()
vs1.valueChanged.connect(partial(move_scrollbar, vs2))
vs2.valueChanged.connect(partial(move_scrollbar, vs1))
I expect the view of the secondary or linked QListwidget update the same way to the primary (the one which i actually scroll) does.
This works for me:
self.vs1 = self.list1.verticalScrollBar()
self.vs2 = self.list2.verticalScrollBar()
self.vs1.valueChanged.connect(self.move_scrollbar)
self.vs2.valueChanged.connect(self.move_scrollbar)
def move_scrollbar(self, value):
self.vs1.setValue(value)
self.vs2.setValue(value)
I have a basic QTableWidget, created with this python code:
from silx.gui import qt
app = qt.QApplication([])
qtw = qt.QTableWidget()
qtw.show()
qtw.setColumnCount(8)
qtw.setRowCount(7)
app.exec_()
The from silx.gui import qt line is just a wrapper that finds out the installed qt wrapper (PyQt4, PyQt5 or PySide) and flattens the qt namespace.
The resulting table has a strange behavior when I edit a cell: as expected, the old text is highligted when I double-click the cell, but the unusual behavior is that the old text remains visible and the new text overlaps with the old one while I'm typing it, until I press enter or I click another cell.
I would like the old text to disappear as soon as I start typing the new one. I know it's possible, because I have an example of program that features a qTableWidget with the behavior I would like to have.
But I cannot find where in that program the cell editing behavior is altered. How can I do this?
Example of "spam" and "eggs" overlayed.
[
EDIT: the code sample without the wrapper business
from PyQt5.Qt import QApplication, QTableWidget, qVersion
app =QApplication([])
print(qVersion())
qtw = QTableWidget()
qtw.show()
qtw.setColumnCount(8)
qtw.setRowCount(7)
app.exec_()
With PyQt4, use this import (also remove the print(qVersion()) line):
from PyQt4.QtGui import QApplication, QTableWidget
My method:
class MyDelegate(QItemDelegate):
def setEditorData(self,editor,index):
editor.setAutoFillBackground(True)
editor.setText(index.data().toString())
Generally, edit behavior is controlled via QItemDelegates. Typically, this is done to provide more advanced editing, or to filter input data or perform some side effects (like update a database) when edits are made. But you can also use it to just clear the editor presented to the user when editing.
class MyDelegate(QItemDelegate):
def setEditorData(self, editor, index):
# Normally, this would set the text of the editor to the current
# value of the cell. If you do nothing here, it will be blank.
editor.clear()
qtw = QTableWidget()
delegate = MyDelegate(qtw)
qtw.setItemDelegate(delegate)
In my case, above problem comes when I set background color of QWidgetTable to transparent. When I remove the setting, there is no old data overlays the new one anymore.
Hope it helps.
You could try connecting the signal emited by QTableWidget cellClicked(int row, int column) with a slot created for clearing the entry. http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html#connecting-disconnecting-and-emitting-signals
I've inserted a simple QTextEdit widget into my PyQt user interface. When the user wants to type text into that widget, he has to click on it. My program should be able to make this happen automatically at certain occasions, such that the user can start typing text into that QTextEdit widget without the need for clicking on it.
I already got somewhere, but the issue is still not solved completely. When my program calls the focus() function, the cursor will start blinking at the end of the last line. But typing on your keyboard doesn't insert any text.
class myTextField(QPlainTextEdit):
def __init__(self):
super(myTextField, self).__init__()
...
def focus(self):
self.focusInEvent(QFocusEvent( QEvent.FocusIn ))
# Now the cursor blinks at the end of the last line.
# But typing on your keyboard doesn't insert any text.
# You still got to click explicitly onto the widget..
...
###
Any help is greatly appreciated :-)
Use setFocus() method.
def focus(self):
self.setFocus()
I have a window containing multiple QRowWidgets, which are custom widgets defined by me. These QRowWidgets contain QLineEdits and other standard widgets. To show or hide certain parts of a QRowWidget, I overdefined the focusInEvent() methodes of all the widgets within it. It works perfectly, when I click on the QRowWidget, the hidden elements appear.
The weird thing is that the blinking cursor line hovewer doesn't appear in the QLineEdits within the custom widgets. I can select them both by a mouse click or with Tab, and a glow effect indicates that the QLineEdit is selected in it, I can select a text in it, or start typing at any location wherever I clicked, but the cursor never appears and it's quite annoying.
My 1st thought was that it is a bug on Mac, but I have the same experience on SuSe Linux.
I'm using python 2.7 and PyQt4.
This is in the __init__() of the QRowWidget:
for i in self.findChildren(QWidget):
i.focusInEvent = self.focusInEvent
And then this is the own focusInEvent():
def focusInEvent(self, event):
if self.pself.focusedLine:
self.pself.focusedLine.setStyleSheet("color: #666;")
self.pself.focusedLine.desc.hide()
self.pself.focusedLine.closebutton.hide()
self.setStyleSheet("color: #000;")
self.desc.show()
self.closebutton.show()
self.pself.focusedLine = self
I suspect you do not make a call to the original focusInEvent() when you override it. Your function should look something like:
def focusInEvent(self,...):
QParent.focusInEvent(self,...)
# the rest of your code
where QParent is the nearest base class for your widgets is.
Either that, or make sure you call focusInEvent() on your QLineEdit widgets as part of your function.
Given the comments, it sounds like you are dynamically reassigning the focusInEvent function on the insantiatations in your custom widget. I would either make a derived class for each of the widgets you use that just overrides focusInEvent as above, or include a line like
type(self).focusInEvent(self,..)
in you function.