I have a QGrid Layout with around 15 widgets consisting of QLabels , QLineEdits and QComboBoxes. I would like a function which extracts the text from only the QLineEdit widgets.
What I mean is something like this
for i in range(self.grid.count()):
if self.grid.itemAt.widget(i).Type == QtGui.QLineEdit: //Not able to figure out the syntax
print self.grid.itemAt.widget(i).text()
Could someone help out with the syntax?
You are using the wrong syntax for itemAt. Try this:
from PyQt4.QtGui import *
...
for i in range(self.grid.count()):
w = self.grid.itemAt(i).widget()
print isinstance(w, QLineEdit)
It should work just fine.
Related
I'm implementing a custom widget to use it as a title bar on a dockable window. My problem arises only on Windows, namely, the window border disappears when the dock window is afloat.
Seems the problem is that, on Windows only, the window flags are changed. I.e. when I do this:
print dock_window.windowFlags()
dock_window.setTitleBarWidget(title_bar)
print dock_window.windowFlags()
it prints out different setting for the flags before and after.
However, it stays the same on linux and the borders remain unchanged.
My question is, how to restore the window border?
UPDATE: Since the custom title bar overrides the flags for the border when the dock window is floating, how can I edit the dock window so it has some kind of border?
(It is crucial for the dock window to have a custom title bar when floating.)
According to this answer this is expected behavior.
From the documentation of setTitleBarWidget:
If a title bar widget is set, QDockWidget will not use native window
decorations when it is floated.
So Linux does it the wrong way then?
Anyway as a workaround for Windows I implemented the idea (unsetting the title bar widget before floating) from the answer in PySide/PyQt.
from PySide import QtGui, QtCore
class MyDockWidget(QtGui.QDockWidget):
def __init__(self, title_widget):
super().__init__()
self.title_widget = title_widget
self.toggle_title_widget(False)
self.topLevelChanged.connect(self.toggle_title_widget)
def toggle_title_widget(self, off):
if off:
self.setTitleBarWidget(None)
else:
self.setTitleBarWidget(self.title_widget)
app = QtGui.QApplication([])
w = QtGui.QMainWindow()
t = QtGui.QLabel('Title')
d = MyDockWidget(t)
w.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d)
w.show()
app.exec_()
At least it keeps the standard decoration when floating.
I found this to be an unresolved bug in QT and I don't see this as expected behavior.
I found multiple cases of people stumbling on this issue eg1, eg2 and others.
Some recommend unsetting and setting the setTitleBarWidget as in Trilarion's answer.
This, however, removes the custom title bar and was not ok with me.
others recommend setting flags on topLevelChanged event: window.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);. this adds the usual title bar to the dock widget, which again is not what I personally want.
the best solution I found is w->setWindowFlags(Qt::Tool|Qt::CustomizeWindowHint);. This uses Qt.CustomizeWindowHint instead of Qt.FramelessWindowHint and does not produce a huge title bar, merely a small bar.
Implementation
from PyQt5.QtCore import Qt
....
def dockfloatevent(isfloating):
if isfloating:
dock.setWindowFlags(Qt.Tool | Qt.CustomizeWindowHint)
dock.topLevelChanged.connect(dockfloatevent)
I am not using the most up to date Qt, but from what I can tell this is still an issue? If someone has a Qt account maybe post something to the above bug link? I have already wasted many hours on this and don't feel like pushing it further :|
I'm building a note-taking GUI with QT Designer and Python. I'm envisioning something that saves the notes as *.txt files with simple markdown. For the GUI, however, I'd like the main text editing box to be able to render markdown live while you're in "edit mode" and typing away. So if you typed *italic* or **bold**, the text box would recognize this and italicize or bold it with those markdown symbols still in the text. Once you exit "edit mode," you'd be left with a preview of the note properly formatted with rich text and none of the markdown symbols. If anybody is familiar with Notable, I'm pretty much looking to replicate that (honorable mention would be the Bear app as well, but that functions differently in that it always stays in the "live preview" mode).
I'm trying to figure out how to go about this with QT and Python and this is all I could come up with so far:
There's a example on the QT website that demonstrates a live preview using QWebEngineView, but that's side-by-side with a normal text box and not what I had in mind.
I wonder if this could also be implemented with some sort of syntax highlighting? So in that sense, I'd be building more a code editor or something? So the QT text box would be configured (as rich text or HTML? I don't know) so that any instances of *(italic text)* would get the italicized formatting the moment you finished typing that second asterisk. I guess in the syntax highlighting definition, I'd be able to use some sort of wildcard character to say "anything between these markdown symbols?"
Does anybody have any suggestions on a solution?
Since Qt 5.14 QTextEdit supports the markdown format so you can use 2 QTextEdit that show the different editing modes. To swap the QTextEdit you can use a QStackedWidget:
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.stacked_widget = QtWidgets.QStackedWidget()
self.setCentralWidget(self.stacked_widget)
self.markdown_editor = QtWidgets.QTextEdit()
self.markdown_viewer = QtWidgets.QTextEdit(readOnly=True)
self.stacked_widget.addWidget(self.markdown_editor)
self.stacked_widget.addWidget(self.markdown_viewer)
foo_menu = self.menuBar().addMenu("&FooMenu")
self.edit_action = foo_menu.addAction("&Edit")
self.edit_action.setCheckable(True)
self.edit_action.triggered.connect(self.handle_edit_mode)
def handle_edit_mode(self):
self.stacked_widget.setCurrentWidget(
self.markdown_viewer
if self.edit_action.isChecked()
else self.markdown_editor
)
if self.stacked_widget.currentWidget() == self.markdown_viewer:
self.markdown_viewer.setMarkdown(self.markdown_editor.toPlainText())
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
I am using PyQt based on Qt4. My Editor is PyCharm 2017.3 and my python version is 3.4. I am scraping some text from a website. I am trying to align that text to the center of the cell in a QTableWidget.
item = QTableWidgetItem(scraped_age).setTextAlignment(Qt.AlignHCenter)
self.tableWidget.setItem(x, 2,item)
Therefore while putting the item in the cell, I am trying to align it as per the documentation. The problem is that the data is not showing up.
It did show up when I removed setTextAlignment method as shown below
item = QTableWidgetItem(scraped_age)
self.tableWidget.setItem(x, 2,item)
This line of code:
item = QTableWidgetItem(scraped_age).setTextAlignment(Qt.AlignHCenter)
will not work properly, because it throws away the item it creates before assigning it to the variable. The variable will in fact be set to None, which is the return value of setTextAlignment(). Instead, you must do this:
item = QTableWidgetItem(scraped_age) # create the item
item.setTextAlignment(Qt.AlignHCenter) # change the alignment
This didn't work for me, and I'm not sure if it is because I'm using PyQt5 or it i did something wrong. I was trying to find something similar but for the whole table, and i finally stumbled upon something that worked and lets you center every cells or just one column at a time.
You have to use the delegate method:
#You're probably importing QtWidgets to work with the table
#but you'll also need QtCore for the delegate class
from PyQt5 import QtCore, QtWidgets
class AlignDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super(AlignDelegate, self).initStyleOption(option, index)
option.displayAlignment = QtCore.Qt.AlignCenter
After implementing this in your code, you can add the following to your main window class or wherever the table is defined:
delegate = AlignDelegate(self.tableWidget)
self.tableWidget.setItemDelegateForColumn(2, delegate) #You can repeat this line or
#use a simple iteration / loop
#to align multiple columns
#If you want to do it for all columns:
#self.tableWidget.setItemDelegate(delegate)
Know this is an old question, but hope it can help someone else.
Bit late to the party but for those of you wondering how to do this on pyqt5
table = QTableWidgetItem() #QTWidgets.QTableWidgetItem() if importing QWidget from PyQt5
table.setTextAlignment(number)
setTextAlignment takes an int for the argument (alignment). Put the number in to get the result:
0:left
1:left
2:right
3:right
4:centre
When I try to insert new rows pressing Enter Key, all looks fine until it exceeds the limit of the window. See example below:
Disalignment example
I tried this (Widget alignment in cell pyqt), that is almost like my problem, but it not fix it.
The next code performs the error:
from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication([])
table = QtWidgets.QTableWidget(0, 1)
def create_empty_row():
widget_completer = QtWidgets.QLineEdit()
widget_completer.returnPressed.connect(
create_empty_row)
_rows = table.rowCount()
table.setRowCount(_rows + 1)
table.setCellWidget(_rows, 0,
widget_completer)
create_empty_row()
table.show()
sys.exit(app.exec_())
I also try to fill the QTableWidget programmaticly and everything looks well and the QLineEdit are not misaligned. But I have to insert new rows by demand.
How can I align the QLineEdit inside QTableWidget?
Thanks!!
EDIT
Solved using resizeRowToContents
You aren't set the correct geometry for the different widgets. So, the problem is the height of the QTableWidget should be ScreenHeight - QLineEdit.height. With this change the QLineEdit geometry it doesn't match with the QTableWidget and should be aligned.
I hope that this help you,
Regards
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