Configuring a custom scrollbar in PyQt
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 dist开发者_如何学JAVAance 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.
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.
精彩评论