PyQt5 How to addWidget at the specific position? [duplicate] - pyqt5

This question already has an answer here:
QHBoxLayout add widget in a different order
(1 answer)
Closed 1 year ago.
I have a vertical layout, that contains one element and a spacer.
When i add widgets to the layout it places below spacer.I'd like to get it on top of a layout.
P.S. to add element, I use this command:
frame.vert_layout.addWidget(wid)

A box layout also has a insertWidget() method that thakes the insert position:
insertWidget(...) method of PyQt5.QtWidgets.QVBoxLayout instance
insertWidget(self, int, QWidget, stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment())
Use that one instead, i.e:
layout.insertWidget(len(layout) - 1, widget_to_add)
len(layout) can be used to get the number of items in the layout.

Related

How do I resize an array of squished PyQt5 widgets? [duplicate]

I have a QScrollArea Widget, which starts empty;
It has a vertical layout, with a QGridLayout, and a vertical spacer to keep it at the top, and prevent it from stretching over the whole scroll area;
Elsewhere in the program, there is a QTextEdit, which when changed, has its contents scanned for "species" elements, and then they are added to the QGridLayout. Any species elements which have been removed are removed too. This bit works;
I have turned the vertical scrollbar on all the time, so that when it appears it does not sit on top of the other stuff in there. Note that the scroll bar is larger than the scroll box already though, despite not needing to be.
This is the problem. The scroll area seems to be preset, and i cannot change it. If i add more rows to the QGridLayout, the scroll area doesn't increase in size.
Instead, it stays the same size, and squeezes the QGridLayout, making it look ugly (at first);
And then after adding even more it becomes unusable;
Note that again, the scroll bar is still the same size as in previous images. The first two images are from Qt Designer, the subsequent 3 are from the program running.
If I resize the window so that the QScrollArea grows, then I see this:
Indicating that there's some layout inside the scroll area that is not resizing properly.
My question is; what do I need to do to make the scrollable area of the widget resize dynamically as I add and remove from the QGridLayout?
If you're coming here from Google and not having luck with the accepted answer, that's because you're missing the other secret invocation: QScrollArea::setWidget. You must create and explicitly identify a single widget which is to be scrolled. It's not enough to just add the item as a child! Adding multiple items directly to the ScrollArea will also not work.
This script demonstrates a simple working example of QScrollArea:
from PySide.QtGui import *
app = QApplication([])
scroll = QScrollArea()
scroll.setWidgetResizable(True) # CRITICAL
inner = QFrame(scroll)
inner.setLayout(QVBoxLayout())
scroll.setWidget(inner) # CRITICAL
for i in range(40):
b = QPushButton(inner)
b.setText(str(i))
inner.layout().addWidget(b)
scroll.show()
app.exec_()
The documentation provide an answer :
widgetResizable : bool
This property holds whether the scroll area should resize the view widget.
If this property is set to false (the default), the scroll area honors the size of its widget.
Set it to true.
Why don't you use a QListView for your rows, it will manage all the issues for you? Just make sure that after you add it you click on the Class (top right window of designer) and assign a layout or it wont expand properly.
I use a QLIstWidget inside a QScrollArea to make a scrollable image list
Try this for adding other objects to the list, this is how I add an image to the list.
QImage& qim = myclass.getQTImage();
QImage iconImage = copyImageToSquareRegion(qim, ui->display_image->palette().color(QWidget::backgroundRole()));
QListWidgetItem* pItem = new QListWidgetItem(QIcon(QPixmap::fromImage(iconImage)), NULL);
pItem->setData(Qt::UserRole, "thumb" + QString::number(ui->ImageThumbList->count())); // probably not necessary for you
QString strTooltip = "a tooltip"
pItem->setToolTip(strTooltip);
ui->ImageThumbList->addItem(pItem);
Update on Artfunkel's answer:
Here's a PySide6 demo that uses a "Populate" button to run the for loop adding items to the scroll area. Each button will also delete itself when clicked.
from PySide6.QtWidgets import *
app = QApplication([])
scroll = QScrollArea()
scroll.setWidgetResizable(True) # CRITICAL
inner = QFrame(scroll)
inner.setLayout(QVBoxLayout())
scroll.setWidget(inner) # CRITICAL
def on_remove_widget(button):
button.deleteLater()
def populate():
for i in range(40):
b = QPushButton(inner)
b.setText(str(i))
b.clicked.connect(b.deleteLater)
inner.layout().addWidget(b)
b = QPushButton(inner)
b.setText("Populate")
b.clicked.connect(populate)
inner.layout().addWidget(b)
scroll.show()
app.exec()

pyqt5 - error zsh: segmentation fault on Mac OS Monterey 12.4 [duplicate]

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

Switch frame if iframe has same name and id in Selenium [duplicate]

This question already has answers here:
Is it possible to switch to an element in a frame without using driver.switchTo().frame("frameName") in Selenium Webdriver Java?
(2 answers)
Closed 3 years ago.
I have frame where id and name is same and I want to switch the frame. How can I do this?
This what I tried:
driver.switchTo().frame("iframe");
driver.switchTo().frame("clntcap_frame");
driver.switchTo().frame("//iframe[#id='clntcap_frame']");
HTML code
<iframe name="clntcap_frame" id="clntcap_frame" style="" xpath="1"></iframe>
In console:
Exception in thread "main" org.openqa.selenium.NoSuchFrameException: No frame element found by name or id iframe
First, make sure that the iframe is present in the DOM. If it is present then followings should work l.
Try this:
In this method, you try to pass the frame element itself.
//To check the element exists or not but avoiding any exception, find all the elements with the id and put them in a list. Since id is a unique identifier, it should return only one.
List<WebElement> frame = driver.findElements(By.id("clntcap_frame"));
//Then check if the list of elements is empty or not. If not, then the frame is present in the DOM
if(!frame.isEmpty()) {
//Since frame is a list we need to get the element in the index 0
driver.switchTo().frame(frame.get(0));
} else {
System.out.println("Frame with this id doesn't exists");
}

How to handle multi select list box using selenium? [duplicate]

This question already has answers here:
How to select multiple options from multi select list using Selenium-Python?
(4 answers)
Closed 3 years ago.
Help me with selenium commands/code to fetch the data from the list. We can only select the data from the list, since entering text(like auto search) is not allowed.
I have used the following code, but couldn't resolve the issue. Also I have doubt regarding which xpath given Do I need to give the xpath of the input field or the drop down list?
*WebElement mySelectElement = driver.findElement(By.xpath("//*[#id='basicBootstrapForm']/div[7]/div/multi-select"));
Select dropdown= new Select(mySelectElement);
dropdown.selectByValue("Arabic");
dropdown.selectByIndex(2);
dropdown.selectByVisibleText("Catalan");*
You need to first click on the dropdwon box and then find out the elemnet you are looking for and then click.Hope this help you.Let me know if this work
driver.findElement(By.id("msdd")).click();
List<WebElement> languages=driver.findElements(By.xpath("//a[#class='ui-corner-all']"));
for(int i=0;i<languages.size();i++)
{
System.out.println(languages.get(i).getText());
if(languages.get(i).getText().equalsIgnoreCase("Arabic"))
{
languages.get(i).click();
break;
}
}

Widget integrated going out of its own zone

I got a main window (Item) with a 640*480 size.
I integrated a custom widget defined in another qml file, its size is 100*100. This item contains a Pathview that only shows 3 items from a list containing a lot of items.
The thing is that when I add my CustomPathView to my main window at coords (0, 0), the PathView goes to the bottom of my main window, displaying 7/8 items... (?!?)
My CustomPathView.qml file starts with :
Item {
width: 100
height: 100
That's why I really don't understand why it is displaying 8 items...
Did I do something wrong ? Do I have to precise to my CustomPathView that he can't go out of its zone (how ?) ?
Thanks in advance for any help about it !
Just set the clip property to true.