'Use PyQt5 to display multiple images choosed from file but failed
I want to select multiple images from a file and display them, but when I click my select button, the images are not displayed.
I used the scrollarea component in PyQt5 to do this, but it failed. How can I solve this problem?
This is a class I designed, in which the height of QWdiget needs to be calculated before scrolling
import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QVBoxLayout, QGridLayout, QScrollArea, QApplication, QPushButton,
QFileDialog)
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import (Qt, QSize)
class Picture(QWidget):
def __init__(self, parent=None, pwidth=980, pheight=350):
super().__init__(parent)
self.mywidth = pwidth
self.myheight = pheight
self.rowheight = 230 # the height of one row
self.labelwidth = 180 #
self.labelheight = 200 #
self.row_picnum = 5 # the number of picture displayed per row
self.setFixedSize(pwidth, pheight)
layout = QGridLayout()
self.setLayout(layout)
# init the display area
self.sc = QScrollArea(self)
self.qw = QWidget(self)
self.sc.setWidget(self.qw)
self.qw.setMinimumSize(self.mywidth, self.myheight)
self.sc.setMinimumSize(self.mywidth, self.myheight)
btn = QPushButton(self)
btn.clicked.connect(self.showimage)
def showimage(self):
imgName, imgType = QFileDialog.getOpenFileNames(self)
print(imgName)
image_address = imgName
# get the number of image
if image_address is not None:
total = len(image_address)
else:
total = 0
# calculate the row number needed
print(total)
if total % self.row_picnum == 0:
rows = int(total / self.row_picnum)
else:
rows = int(total / self.row_picnum) + 1
# display the image one by one
for i in range(total):
# set the image
per_picture = image_address[i]
photo = QPixmap(per_picture)
width = photo.width()
height = photo.height()
tmp_image = photo.toImage()
size = QSize(width, height)
photo.convertFromImage(tmp_image.scaled(size, Qt.IgnoreAspectRatio))
# init the widget used by image
tmp = QWidget(self.qw)
vl = QVBoxLayout()
# use the label to display image
label = QLabel()
label.setFixedSize(self.labelwidth, self.labelheight)
label.setStyleSheet("border:1px solid gray") # 设置每个标签的样式
label.setPixmap(photo)
label.setScaledContents(True)
vl.addWidget(label)
tmp.setLayout(vl)
tmp.move(190 * (i % self.row_picnum), self.rowheight * int(i / self.row_picnum))
if __name__ == '__main__':
app = QApplication(sys.argv)
pic = Picture()
pic.show()
sys.exit(app.exec_())
Solution 1:[1]
There are a few problems with your UI. First there is no layout, you initialize one but you never add anything to it so all your widgets are just floating up to the top left corner of the screen. Second you setting the Main QWidget, the scroll area and the inner scroll area all to be the same height and width, which is impossible since they are each nested within one another. Lastly when you create your image labels. you create an layout and widget for them but that's it so they are either overwritten on the next loop or they are just floating too.
Below is an example of what you could do with the layouts to at least make the images appear in the widget. It should at least point you in the right direction.
import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QVBoxLayout, QGridLayout, QScrollArea, QApplication, QPushButton, QHBoxLayout,
QFileDialog)
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import (Qt, QSize)
class Picture(QWidget):
def __init__(self, parent=None, pwidth=980, pheight=350):
super().__init__(parent)
self.mywidth = pwidth
self.myheight = pheight
self.rowheight = 230 # the height of one row
self.labelwidth = 180 #
self.labelheight = 200 #
self.row_picnum = 5 # the number of picture displayed per row
self.setFixedSize(pwidth, pheight)
layout = QGridLayout()
self.setLayout(layout)
# init the display area
self.sc = QScrollArea(self)
self.sc_layout = QHBoxLayout()
self.sc.setLayout(self.sc_layout)
# self.sc.setMinimumSize(self.mywidth, self.myheight)
btn = QPushButton(self)
btn.clicked.connect(self.showimage)
layout.addWidget(self.sc, 0, 0)
layout.addWidget(btn, 1, 0)
def showimage(self):
imgName, imgType = QFileDialog.getOpenFileNames(self)
print(imgName)
image_address = imgName
# get the number of image
if image_address is not None:
total = len(image_address)
else:
total = 0
# calculate the row number needed
print(total)
if total % self.row_picnum == 0:
rows = int(total / self.row_picnum)
else:
rows = int(total / self.row_picnum) + 1
# display the image one by one
for i in range(total):
# set the image
per_picture = image_address[i]
photo = QPixmap(per_picture)
width = photo.width()
height = photo.height()
tmp_image = photo.toImage()
size = QSize(width, height)
photo.convertFromImage(tmp_image.scaled(size, Qt.IgnoreAspectRatio))
tmp = QWidget(self)
tmp_layout = QVBoxLayout()
tmp.setLayout(tmp_layout)
# use the label to display image
label = QLabel()
label.setFixedSize(self.labelwidth, self.labelheight)
label.setStyleSheet("border:1px solid gray") # ?????????
label.setPixmap(photo)
label.setScaledContents(True)
self.sc_layout.addWidget(tmp)
tmp_layout.addWidget(label)
tmp.move(190 * (i % self.row_picnum), self.rowheight * int(i / self.row_picnum))
if __name__ == '__main__':
app = QApplication(sys.argv)
pic = Picture()
pic.show()
sys.exit(app.exec_())
Solution 2:[2]
A nested Start-Process should work. Lasse V. Karlsen suggestion would be the recommended way to go.
Start-Process powershell -Verb RunAs -ArgumentList @'
Start-Process 'C:\test\test.bat'
Start-Process 'C:\test1\test.bat'
Start-Process 'C:\test2\test.bat'
'@ -Wait
Or with a loop:
Start-Process powershell -Verb RunAs -ArgumentList @'
'C:\test\test.bat','C:\test1\test.bat','C:\test2\test.bat' |
ForEach-Object { Start-Process $_ }
'@ -Wait
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | alexpdev |
| Solution 2 |
