在 PyQt 中配置自定义滚动条

发布于 2024-11-11 05:35:39 字数 1860 浏览 5 评论 0原文

我正在 PyQt 中构建用于图像处理的 GUI。我需要做的一项任务是使用滚动条在图像文件目录中移动。具体来说,如果 /my/dir 中有 1000 个图像,那么我希望沿着滚动条滚动的距离对应于图像编号(1 到 1000 之间)。因此,从左到右的滚动条为 image = 1,从右到右的滚动条为 image = 1000,如果滚动条从左到右为 33%,则显示的图像为数值 round(0.33333*1000) = 333。

现在我有一组工作小部件,可以从目录中绘制图像,然后有“下一个”和“上一个”按钮,您可以使用它们来向前和向后导航。该软件的目的是允许通过深入的人工注释进行监督学习,因此需要快速滚动大量没有发生有意义的变化的图像。这就是为什么我需要滑块。

如果整个插槽/信号内容对于滚动条的作用与对于按钮的作用相同,那么我确信我可以破解这些内容,使其能够操纵像素图图像名称并更新显示的图像。不过,我需要的帮助是一些基本语法,解释如何创建滚动条类,并将其放置在 QGridLayout 框架上的像素图下方。


我通过冲浪和修补找到的答案如下。

我找到了另一个接口良好的解决方案,尽管我喜欢@Stephen Terry 的建议,即实际迭代文件本身。我的解决方案基于此处找到的教程代码: http://zetcode.com/tutorials/pyqt4/widgets /

我通过首先创建自己的一个小类来修改它:

class InterpolatingScrollBar(QtGui.QWidget):

    def __init__(self,parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.testbar = QtGui.QSlider(QtCore.Qt.Horizontal,self)
        self.testbar.setGeometry(10,10,500,30)
        self.testbar.setFocusPolicy(QtCore.Qt.NoFocus)

然后在主控制器类中创建此类的实例,

    self.scrollbar = buttonUtils.InterpolatingScrollBar()
    self.scrollbar.testbar.setMinimum(self.overall_counter)
    self.scrollbar.testbar.setMaximum(self.max_image_num)

其中 max_image_num 是通过对 glob() 执行类似的调用并检查哪些是来计算的目录中的 jpg。然后我使用此代码连接到滚动条的“值已更改”信号:

    self.connect(self.scrollbar.testbar,QtCore.SIGNAL('valueChanged(int)'),self.getScrollValue)

def getScrollValue(self,value):
        self.overall_counter = value
        self.pb1.previousSlot(self.overall_counter)
        self.nb1.nextSlot(self.overall_counter)
        self.pixmap = QtGui.QPixmap(self.directory_name + self.pb1.new_image_str)
        self.label.setPixmap(self.pixmap)

其中 pb1 和 nb1 是“上一个按钮”和“下一个按钮”,以及更新这些按钮上显示的计数器以及字符串名称的相应函数导致显示新图像。

I am building a GUI for image processing in PyQt. One task that I need to be able to do is use a scrollbar to move through a directory of image files. Specifically, if there are 1000 images, say, in /my/dir, then I would like the distance scrolled along a scrollbar to correspond to the image number (between 1 and 1000). So the scrollbar all the way at the left would be image = 1, the scrollbar all the way at the right would be image = 1000, and if the scroll bar is 33% of the way from left to right, then the image displayed has the numeric value round(0.33333*1000) = 333.

Right now I have a working set of widgets that will draw an image from a directory, and then has 'Next' and 'Previous' buttons which you can use to navigate forward and backward. The point of this software is to allow for supervised learning via deep human annotations, so there is a need to rapidly scroll through large amounts of images in which no meaningful changes happen. That's why I need the slider bar.

If the whole slot/signal stuff works the same for scrollbars as it does for buttons, I am sure I can hack my way through that stuff to get it to manipulate the pixmap image name and update the displayed image. What help I need though is some basic syntax explaining how to create a scrollbar class, and place it beneath my pixmap on a QGridLayout frame.


An answer I found through surfing and tinkering is below.

I found another solution which interfaces well, although I like @Stephen Terry's suggestion to actually iterate over the files themselves. My solution is based off of tutorial code found here: http://zetcode.com/tutorials/pyqt4/widgets/

I modified this by first creating a small class of my own:

class InterpolatingScrollBar(QtGui.QWidget):

    def __init__(self,parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.testbar = QtGui.QSlider(QtCore.Qt.Horizontal,self)
        self.testbar.setGeometry(10,10,500,30)
        self.testbar.setFocusPolicy(QtCore.Qt.NoFocus)

and then creating an instance of this class in the main controller class,

    self.scrollbar = buttonUtils.InterpolatingScrollBar()
    self.scrollbar.testbar.setMinimum(self.overall_counter)
    self.scrollbar.testbar.setMaximum(self.max_image_num)

where max_image_num is computed by doing a similar call to glob() and checking for which are jpgs in the directory. Then I use this code to connect to the 'value changed' signal of the scrollbar:

    self.connect(self.scrollbar.testbar,QtCore.SIGNAL('valueChanged(int)'),self.getScrollValue)

def getScrollValue(self,value):
        self.overall_counter = value
        self.pb1.previousSlot(self.overall_counter)
        self.nb1.nextSlot(self.overall_counter)
        self.pixmap = QtGui.QPixmap(self.directory_name + self.pb1.new_image_str)
        self.label.setPixmap(self.pixmap)

where pb1 and nb1 are 'previous button' and 'next button', with corresponding functions that update counters displayed on those buttons, as well as the string name leading to the new image to be displayed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浪漫人生路 2024-11-18 05:35:39

最简单的方法是使用 QListWidget 并填充它您的图像作为 QListWidgetItem。一个例子是这样的,

self.list_widget = QListWidget()
files = glob.glob('YourDirectory/*.jpg') #Get all jpegs in your directory
for i in files:
    self.list_widget.addItem(QListWidgetItem(QIcon(i),'your text here'))
self.list_widget.setIconSize(QSize(400,300)) #Set your image size

这将使您接近您想要的滚动条行为;用户将能够一次看到多个图像,除非您将图像设置得足够大以填满屏幕。希望您可以对其进行调整以满足您的需求。

The simplest way would be to use a QListWidget and populate it with your images as the icons of a QListWidgetItem. An example would be something like this

self.list_widget = QListWidget()
files = glob.glob('YourDirectory/*.jpg') #Get all jpegs in your directory
for i in files:
    self.list_widget.addItem(QListWidgetItem(QIcon(i),'your text here'))
self.list_widget.setIconSize(QSize(400,300)) #Set your image size

That will give you close to the scrollbar behavior you want; the user will be able to see more than one image at a time unless you make the images large enough to fill the screen. Hopefully you can tweak it to meet your needs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文