How to move items between two QListWidgets? - python

I want to create a pyqt5 GUI in which the user should pick the wanted variables on the left and they should show up on the right hand side. This is what the GUI looks like:
Basically, I want to click the variables on the left listWidget, and they should show up in the list widget on the right (chosenitem_list), and then ideally dissapear from the left listWidget. Otherwise, I could add a button once all the desired variables have been selected which transfers them to the other side. I am trying to do this using the item_clicked method in my code below, but when I click on them nothing happens so I am stuck. What am I doing wrong?
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
loadUi('browse.ui',self)
self.listWidget.clicked.connect(self.item_clicked)
def item_clicked(self):
item = QtWidgets.QListWidgetItem()
item = self.listWidget.currentItem()
self.chosenitem_list.addItem(item)

You have to clone the QListWidgetItem:
def item_clicked(self, index):
item = self.listWidget.itemFromIndex(index)
it = item.clone()
self.chosenitem_list.addItem(it)

Related

Python Tkinter Removing a Frame on button click

I'm trying to make an application that has the functionality to add and remove frames based on a button click. For now, I'm trying to get it to remove the last frames added from the root and will add in the functionality to specify what frame to delete later.
When I create the frame, I add it to a list of objects like this:
def AddFrame(self):
newFrame= customFrame(len(self.frameList))
self.frameList.append(newFrame)
newFrame.pack()
As I'm trying to delete it by reference, I'm using pop and pack_forget to both remove it from the list and removing it from the GUI. My basic function is:
def RemoveLastFrame(self):
if(len(self.frameList)>0):
self.frameList.pop().pack_forget()
I tried the pack_forget by testing it on a specified frame that I made in the init method. I'm not sure if this issue is coming from me trying to do this on a list of frame objects, or if it's due to the frame object's being a child of tk.Frame. Here is the child class in full:
class customFrame(tk.Frame):
def __init__(self, index):
super(customFrame, self).__init__()
self.index = index
self.buttons= []
self.addButton = tk.Button(command=self.AddButton,text='Add Button to Frame')
self.addButton.pack()
def AddButton(self):
newButton = customButton(len(self.buttons))
newButton.config(text=('Button '+str(newButton.index)))
self.buttons.append(newButton)
newButton.pack()
class customButton(tk.Button):
def __init__(self,index):
super(customButton, self).__init__()
self.index = index
I am an idiot. It was working, but it didn't unpack the children of the frame as well as I expected it to. Once I changed that, it works perfectly

PyQT - QlistWidget with infinite scroll

I have a QlistWidget and I need to implement on this an Infinite Scroll, something like this HTML example:
https://scrollmagic.io/examples/advanced/infinite_scrolling.html
Basically, when the user scrolls to the last item of the list, I need to load more items and dynamically append it in the QlistWidget.
Is it possible? I didn't find any example yet.
There are likely many ways to achieve this task, but the easiest I found is to watch for changes in the scroll bar, and detect if we're at the bottom before adding more items to the list widget.
import sys, random
from PyQt5.QtWidgets import QApplication, QListWidget
class infinite_scroll_area(QListWidget): #https://doc.qt.io/qt-5/qlistwidget.html
def __init__(self):
super().__init__() #call the parent constructor if you're overriding it.
#connect our own function the valueChanged event
self.verticalScrollBar().valueChanged.connect(self.valueChanged)
self.add_lines(15)
self.show()
def valueChanged(self, value): #https://doc.qt.io/qt-5/qabstractslider.html#valueChanged
if value == self.verticalScrollBar().maximum(): #if we're at the end
self.add_lines(5)
def add_lines(self, n):
for _ in range(n): #add random lines
line_text = str(random.randint(0,100)) + ' some data'
self.addItem(line_text)
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = infinite_scroll_area()
sys.exit(app.exec_())
You can directly grab scroll wheel events by overriding the wheelEvent method of QListWidget, then do the logic there which solves the potential problem of not starting out with enough list items for the scrollbar to appear. If it's not there, it can't change value, and the event can't fire. It introduces a new problem however as scrolling with the mouse wheel is not the only way to scroll the view (arrow keys, page up/down keys, etc). With the number of classes and subclasses in any gui library, it becomes imperative to get really familiar with the documentation. It's a little inconvenient that it isn't as comprehensive for python specifically, but I think the c++ docs are second to none as far as gui library documentation goes.

Changing icon in nested menus

I don't think this may be posssible but I had still want to try asking.
In the attached screenshot, I have nested menus.
Is it possible to change the arrow keys icon as 'highlighted' by the red box?
I am trying to change the arrow key to a plus icon if there are no sub menu items found.
The default arrow can be in use if there are sub menu items found.
Yes, you can change the color of right-arrow.
But there is a trick to change it.
The truth of indicator is "branch-closed png file"
You can see the png file at the almost bottom on the page in the link.
So, it can not be solved by the pure-programmic way.
You prepare the picture in advance by yourself.
and please following code in QMenu constructor.
self.setStyleSheet("QMenu::right-arrow{image:url(stylesheet-branch-closed-red.png);}")
Attention:
stylesheet-branch-closed-red.png is my renamed picture.
You can download the original picture from the above link page.
you right-click the png picture and save as name.
This code comes from your past question.
class QCustomMenu(QtGui.QMenu):
"""Customized QMenu."""
def __init__(self, title, parent=None):
super(QCustomMenu, self).__init__(title=str(title), parent=parent)
self.setup_menu()
self.setStyleSheet("QMenu::right-arrow{image:url(stylesheet-branch-closed-red.png);}")
def setup_menu(self):
self.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
def contextMenuEvent(self, event):
no_right_click = [QAddAction]
if any([isinstance(self.actionAt(event.pos()), instance) for instance in no_right_click]):
return
pos = event.pos()
def addAction(self, action):
super(QCustomMenu, self).addAction(action)
As the result, it will become like this.
You will dislike the white part of the arrow.
No problem, you can delete them clearly with a free-paint soft, but I didn't do it because it was needless.

How to place an image at a certain position in QtGraphicsView/QtGraphicsScene (PyQt4)?

I'm creating an application using Qt Designer and PyQt4. I want to know how I can add an image to the QtGraphicsView widget to my desired location.
For example, when I click on the QtGraphicsView widget, I want to add an image to that exact location. I've searched online but I couldn't find anything that was of any help.
I've created a scene subclass to manage the items that will be displayed in the QtGraphicsView widget. I'm able to get the coordinates of the place where I click but I don't know how to place the item in that certain position. Below is my code:
class graphicsScene(QtGui.QGraphicsScene):
def __init__(self, parent=None):
super(graphicsScene, self).__init__(parent)
def mousePressEvent(self, event):
position = QtCore.QPointF(event.scenePos())
pixmap = QtGui.QPixmap("host.png")
pixmap_scaled = pixmap.scaled(30, 30, QtCore.Qt.KeepAspectRatio)
self.itemAt(pixmap_scaled,position.x(),position.y())
self.addPixmap(pixmap_scaled)
print "pressed here: " + str(position.x()) + ", " + str(position.y())
self.update()
def mouseReleaseEvent(self, event):
position = QtCore.QPointF(event.scenePos())
print "released here: " + str(position.x()) + ", " + str(position.y())
self.update()
class form(QtGui.QMainWindow):
def __init__(self):
super(mininetGUI, self).__init__()
self.ui = uic.loadUi('form.ui')
self.scene = graphicsScene()
self.ui.view.setScene(self.scene)
Use addItem(your_pixmap_object) to add the QPixmap to the scene. Then you can use setPos(...) on the returned QGraphicsItem (this is returned when you use addItem(...) and the insertion of the item into the scene was succcessful).The point that you pass to your setPos(...) would be the one that is part of the event (as you have done already by calling event.scenePos()).
pixmap = QPixmap(...)
sceneItem = self.addItem(pixmap)
sceneItem.setPos(event.scenePos())
If you want to use QGraphicsPixmapItem the procedure is the same as the one above but just use self.addPixmap(...) as you have done in your code.
There is one thing that you might want to handle in addition to just placing the item - the case where you press the mouse button, move the cursor somewhere else in the scene while still pressing the button and then release it. This will insert the item at the starting position of your movement event (while pressing the button and moving) however this might not be what you want to do. You have to think about whether it will be better to handle the insertion inside the mouseReleaseEvent(...) instead. It really depends on how you want things to work for this particular scenario.

Updating the contents in QMenu 'live'

I have a UI in which it consists of a few QPushButton and a QLineEdit and currently I am having trouble to 'update' the contents within this QMenu that was attached onto a QPushButton.
So assumingly, if there are already 2 cameras in my scene, and as I execute my UI, by pressing onto this setCameraBtn I will get the 2 cameras in the list. However, if I create a new camera where the UI is not yet close, how do I make my QMenu to read in the new camera, like a 'live-update'?
I tried creating another function where it re-read the cameras in scene and retabulate the camLs as well as a connection similar to the one that I have written in the createConnections but it does not seems to be reading in.
camLs = []
class orientCameraUI(QDialog):
def __init__(self, parent=None):
...
...
def initUI(self):
...
...
def createConnections(self):
self.connect(self.orientToCamBtn, SIGNAL('clicked()'), self.orientToCam)
def camMenu(self):
allCams = [cam for cam in cmds.listRelatives(cmds.ls(cameras=1),parent=1) if cam not in ['front','persp','side','top']]
camLs.extend(allCams)
menu = QMenu("menu", self.setCameraBtn)
for item in camLs:
menu.addAction(QAction(item, menu))
self.setCameraBtn.setMenu(menu)
menu.triggered.connect(self._camSelected)
def _camSelected(self, action):
self.currentCamTxt.setText(action.text())
This can be easily accomplished by firing a QThread instead the UI that periodically call a update camera method which checks for the current cameras in the scene and compares them with the one that the UI has already registered. And if there is an addition, change or deletion in the camera(s) then it updates the menu to reflect it.
Another solution is to use scriptJob.

Categories

Resources