How to make an image selectable using pixmap and Qlabel? - python

I am trying to show multiple images using Pyqt5. It would be nice to make the image selectable within the GUI so that the users can select and copy that image right away easily.
By "selectable", I meant the user can right click the image and then copy it and then potentially paste it to somewhere else outside of the GUI. Just like a normal image saved in a Word. User can select/copy an image in Word and then paste it to somewhere else.
I know for Text in Qlabel this can easily achieved by using self.my_label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse). However, it seems for images there is no such method handling it. Is there any way I can work it out for images?
import sys
import PyQt5
from PyQt5.QtWidgets import (
QLabel,
QVBoxLayout,
QWidget
)
from PyQt5 import QtCore
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import QSize
class Display_Window(QWidget):
def __init__(self):
super().__init__()
self.setMinimumSize(QSize(980,700))
self.layout = QVBoxLayout(self)
self.label1 = QLabel(self)
self.pixmap = QPixmap(path_to_my_image)
self.pixmap = self.pixmap.scaled(900, 900, QtCore.Qt.KeepAspectRatio)
self.label1.setPixmap(self.pixmap)
self.label1.resize(self.pixmap.width(), self.pixmap.height())
# Run if Script
if __name__ == "__main__":
app = PyQt5.QtWidgets.QApplication(sys.argv)
MainWindow = Display_Window() # Initialize GUI
MainWindow.show() # Show Window
app.exec_()

You can subclass the label and create a menu whenever it has a valid pixmap, then use the system clipboard to copy it.
class CopiableLabel(QLabel):
def contextMenuEvent(self, event):
pixmap = self.pixmap()
if not pixmap.isNull():
menu = QMenu()
copyAction = menu.addAction('Copy image to clipboard')
if menu.exec_(event.globalPos()) == copyAction:
QApplication.clipboard().setPixmap(pixmap)
return
super().contextMenuEvent(event)
class Display_Window(QWidget):
def __init__(self):
super().__init__()
self.layout = QVBoxLayout(self)
self.label1 = CopiableLabel(self)
self.layout.addWidget(self.label1)
self.pixmap = QPixmap(path_to_my_image)
self.pixmap = self.pixmap.scaled(900, 900, Qt.KeepAspectRatio)
self.label1.setPixmap(self.pixmap)
Note that setting a pixmap on a QLabel automatically resizes it (unless it has the scaledContents property set to True.
You also should add the label to the layout, as I did in the above modifications.

Related

PyCharm giving cannot find reference and unexpected argument warnings when working with inherited classes from PyQt6 despite code working normally

I am trying to make a calculator app using PyQt6 and I wanted a QPushButton with fixed size to go into a grid layout. I was going to be using this button a lot so I created my own SquarePushButton class inheriting from QPushButton with an additional setMinimumSize and setMaximumSize already in the init function.
I simplified the code as much as possible while replicating the error which is why I am using a QGridLayout for just two widgets.
When I run it, the code works perfectly fine and as expected.
import sys
from PyQt6.QtCore import QSize
from PyQt6.QtWidgets import QWidget, QApplication, QPushButton, QLabel, QGridLayout
# class to have a button of fixed size
class SquarePushButton(QPushButton):
def __init__(self, text):
super().__init__()
self.setText(text)
self.setMinimumSize(QSize(50, 50))
self.setMaximumSize(QSize(50, 50))
# main window class
class MyWindow(QWidget):
def __init__(self):
super().__init__()
# create a text label
self.label = QLabel(self)
self.label.setText("Label")
# create a button
btn = SquarePushButton("Button")
btn.clicked.connect(self.buttonPressed)
# error: "Cannot find reference 'connect' in 'function'"
# add text label into layout
layout = QGridLayout()
layout.addWidget(self.label, 0, 0)
layout.addWidget(btn, 0, 1)
# sets the layout
self.setLayout(layout)
def buttonPressed(self):
self.label.setText("Pressed")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec())
Here it gives me an error saying "Cannot find reference 'connect' in 'function'"
However if I change how the QWidgets are imported I get a new error at a completely different location, this time the error occurs during layout.addWidget, where it says "unexpected argument" for the last two arguments.
Keep in mind everything still works, its just PyCharm IDE getting mad at me.
import sys
from PyQt6.QtCore import QSize
from PyQt6.QtWidgets import *
# class to have a button of fixed size
class SquarePushButton(QPushButton):
def __init__(self, text):
super().__init__()
self.setText(text)
self.setMinimumSize(QSize(50, 50))
self.setMaximumSize(QSize(50, 50))
# main window class
class MyWindow(QWidget):
def __init__(self):
super().__init__()
# create a text label
self.label = QLabel(self)
self.label.setText("Label")
# create a button
btn = SquarePushButton("Button")
btn.clicked.connect(self.buttonPressed)
# add text label into layout
layout = QGridLayout()
layout.addWidget(self.label, 0, 0)
layout.addWidget(btn, 0, 1)
# error: "unexpected argument"
# sets the layout
self.setLayout(layout)
def buttonPressed(self):
self.label.setText("Pressed")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec())
Note: It would be easiest to spot if you just copy and pasted the code into your PyCharm IDE because it highlights the supposed error.
I do not understand why there is an error there, everything seems to be working fine so is this a PyCharm bug, PyQt6 bug or am I just using inheritance incorrectly? I am quite new to Python still so sorry if this is really stupid.

Widgets are not displayed

I'm currently doing a tutorial on how to create GUI apps from a book called "Modern PyQt" by Joshua Willman and I'm stuck right out of the gate:
I've copy pasted a basic code snippet from the book and tried to tweak it bit by bit instead of reading a bunch of text without any practical trial and error. I can display a window and adjust it's size and properties, but when I try to attach other widgets to the main window, they just don't show up.
Here's what I've got so far:
# First practical example from the book: Pomodoro time manager
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtGui import QIcon
class Pomodoro(QWidget):
def __init__(self): # Create default constructor
super().__init__()
self.initializeUI()
def initializeUI(self):
"""Initialize the window and display its contents to the screen."""
self.setGeometry(int((SCREEN_WIDTH-WINDOW_WIDTH)/2),int((SCREEN_HEIGHT-WINDOW_HEIGHT)/2),WINDOW_WIDTH,WINDOW_HEIGHT) # x,y,w,h
self.setWindowTitle('Bortism')
# self.setWindowIcon(QIcon("Borticon.png"))
self.button1 = QPushButton()
self.button1.setText('Button')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
WINDOW_WIDTH, WINDOW_HEIGHT = 1000,600
SCREEN_X, SCREEN_Y, SCREEN_WIDTH, SCREEN_HEIGHT = app.desktop().screenGeometry().getRect()
window = Pomodoro()
sys.exit(app.exec_())
For a widget to be shown as part of another then the requirement is that the first is the child of the second. This can be done by passing the parent or by using a layout (which is also passed to it by the parent). So in your case you must change to:
self.button1 = QPushButton(self)

PyQt5 widgets intended to be transparent to show QVideoPlayer pass through video and adopt QMainWindow background

I have a QMainWindow with a QVideoWidget set as the central widget. The video is acting like a background to the main window of the blackjack game I'm making. I have two buttons I'd like to place on top of the video with partial transparency.
This is what I want the window to look like:
but I've tried seemingly dozens of ways to achieve the transparent button background and can't. Any attempt at transparency 'cuts' straight through the video and shows the background of the MainWindow instead. For example, I have the main window background set to blue.
This is what shows when run:
How can I make the video appear behind the transparent buttons instead?
Things I've tried without success: stacked layouts set to StackAll, inserting transparent background images in the button stylesheets, using transparent color codes (rgba(0,0,0,0)), setting the videowidget as the parent widget to the buttons.
The relevant portion of my code:
from PyQt5 import QtWidgets, QtMultimediaWidgets, QtMultimedia, QtCore, QtGui, Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QLineEdit, QComboBox
from PyQt5.QtGui import QTransform
import sys
import random
class MyWindow(QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.setGeometry(0, 0, 1920, 1080)
self.setWindowTitle("Cutie Pie Casino")
self.setStyleSheet('background-color: blue;')
self.Welcome()
def Welcome(self):
welcome_font = QtGui.QFont()
welcome_font.setPointSize(30)
welcome_font.setFamily('Broadway')
welcome_font_small = QtGui.QFont()
welcome_font_small.setPointSize(20)
welcome_font_small.setFamily('Broadway')
# create link to movie file
movie_file = QtCore.QUrl.fromLocalFile('C:/Users/Owner/PycharmProjects/Black Jack/video/'
'Cutie Pie Casino Video.mp4')
vid_media = QtMultimedia.QMediaContent(movie_file)
# create video widget
self.videoWidget = QtMultimediaWidgets.QVideoWidget()
self.videoWidget.setGeometry(0,0,1920,1080)
self.videoWidget.setStyleSheet('background-color: blue')
# create media player object (video widget goes in media player)
self.mediaPlayer = QtMultimedia.QMediaPlayer(None,
QtMultimedia.QMediaPlayer.VideoSurface)
self.mediaPlayer.setVideoOutput(self.videoWidget)
# playlist
self.playlist = QtMultimedia.QMediaPlaylist()
self.playlist.setCurrentIndex(0)
self.playlist.setPlaybackMode(QtMultimedia.QMediaPlaylist.Loop)
self.playlist.addMedia(vid_media)
# add content to media player
self.mediaPlayer.setPlaylist(self.playlist)
self.mediaPlayer.play()
self.setCentralWidget(self.videoWidget)
self.PlayCardsButton = QPushButton(self)
self.PlayCardsButton.setText('Play Blackjack')
self.PlayCardsButton.setFont(welcome_font_small)
self.PlayCardsButton.setGeometry(765,500,400,150)
self.PlayCardsButton.clicked.connect(self.InitializeTable)
self.PlayCardsButton.setStyleSheet('background-color: rgba(0,0,0,0); color: black')
self.GameSetupButton = QPushButton(self)
self.GameSetupButton.setGeometry(765, 700, 400, 150)
self.GameSetupButton.setFont(welcome_font_small)
self.GameSetupButton.setText('Game Setup')
self.GameSetupButton.setStyleSheet('background-color: rgba(0,0,0,0); color: black')
You could try with:
self.PlayCardsButton.setFlat(True)

pyqt5 / qtdesigner textbox default label

I am trying to create a GUI for my python program. One of the tools that I need is a text input box.
Now, I want a text label for this box saying "Please insert texts." Is there a function to add a label that shows inside the input textbox as default and disappear when user click the box to type?
I don't mind to use qt designer or pyqt5 coding.
Thank you guys.
placeholderText : QString
This property holds the line edit's placeholder text
import sys
from PyQt5.QtWidgets import QLineEdit, QVBoxLayout, QApplication, QWidget
class Test(QWidget):
def __init__(self):
super().__init__()
self.lineEdit = QLineEdit(placeholderText="Please insert texts.") # <---
vbox = QVBoxLayout(self)
vbox.addWidget(self.lineEdit)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Test()
w.show()
sys.exit(app.exec_())
I am begginer like you and my English is not so good. But I recommend you use Qt Designer. It's easier, fastter for you draw your app. I am using pyside2 project and recommend you read docummentatio each widgets you wanna use in PySide2 project and Qt Project. Try code below
enter image description here
import sys
from PySide2.QtWidgets import QApplication
from PySide2.QtWidgets import QDialog
from PySide2.QtWidgets import QTextEdit
from PySide2.QtWidgets import QVBoxLayout
from PySide2.QtCore import Qt
class MainDialog(QDialog):
def __init__(self, parent=None):
super(MainDialog, self).__init__(parent)
# Create Widget TextEdit
self.text = QTextEdit()
# I think that you wanna this function in your program
# https://doc.qt.io/qtforpython/PySide2/QtWidgets/QLineEdit.html?highlight=qlineedit#PySide2.QtWidgets.PySide2.QtWidgets.QLineEdit.setPlaceholderText
# http://doc.qt.io/qt-5/qlineedit.html#placeholderText-prop
self.text.setPlaceholderText('''Yes! this is exactly what I want!
Thank you, what if you have a big text box (more than 10 lines) and
you want to scale up the place holder and align it in center?? ''')
# https://doc.qt.io/qtforpython/PySide2/QtWidgets/QLineEdit.html?highlight=qlineedit#PySide2.QtWidgets.PySide2.QtWidgets.QLineEdit.setAlignment
# http://doc.qt.io/qt-5/qlineedit.html#alignment-prop
self.text.setAlignment(Qt.AlignCenter)
# Layout
layout = QVBoxLayout()
layout.addWidget(self.text)
self.setLayout(layout)
def main():
app = QApplication()
mainDialog = MainDialog()
mainDialog.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Python PyQt4 how to open image using QFileDialog

I have to write a program with an option to open an image from a file. I have to use QFileDialog and display image in QLabel, using QPixmap. I am able to use them individually but I didn't manage to combine them.
I think I need to take my image name from dlg.selectedFiles but I don't know how to choose the moment when there is useful data in it. Do I need to make a loop in my main program, and constantly check if there is image to open? Can I send a signal to my label using openAction.triggered.connect(...)?
from PyQt4 import QtGui
import sys
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent = None):
super(MainWindow, self).__init__(parent)
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
dlg = QtGui.QFileDialog(self)
openAction = QtGui.QAction('Open', self)
openAction.triggered.connect(dlg.open)
fileMenu.addAction(openAction)
#label = QtGui.QLabel(self)
#pixmap = QtGui.QPixmap('')
#label.setPixmap(pixmap)
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
win.show()
app.exec_()
if __name__ == '__main__':
sys.exit(main())
You need to make your own slot and connect it to the openAction signal.
In your __init__ function do:
openAction.triggered.connect(self.openSlot)
In your class MainWindow define the following function:
def openSlot(self):
# This function is called when the user clicks File->Open.
filename = QtGui.QFileDialog.getOpenFileName()
print(filename)
# Do your pixmap stuff here.

Categories