QLabel is not clickable in my program - qt

The program is working correctly but QLabel is not clickable.
from PyQt5.QtWidgets import *
import sys
import bs4
import urllib.request
from PyQt5.QtWidgets import *
import sys
from PyQt5.QtWidgets import QApplication
webpage=urllib.request.urlopen('http://www.boluolay.com/')
soup = bs4.BeautifulSoup(webpage, 'html.parser')
class ButonluPencere(QWidget):
def __init__(self):
super().__init__()
self.resize(640, 480)
buton = QPushButton(self)
buton.setText("Bolu Olay Gazetesi")
buton.setGeometry(400,10,100,50)
buton.clicked.connect(self.getir)
kayan=QScrollBar(self)
kayan.setGeometry(370, 60, 16, 160)
buton.clicked.connect(self.boluolay_koseyazilari)
buton.clicked.connect(self.boluolay_manset)
def getir(self):
boluolay_manset=QLabel(self)
boluolay_manset.setText("MANŞET")
boluolay_manset.setGeometry(100,-15,500,70)
boluolay_manset.show()
satirBoyu=20
i=1
for yazarlar in soup.find_all("a",class_="main_cuff"):
for yazar_adi in yazarlar.find_all("div",class_="title"):
etiket = QLabel(self)
etiket.setOpenExternalLinks(True)
etiket.setGeometry(100,satirBoyu,500,satirBoyu+20)
etiket.setText(''+str(i) + ". " + yazar_adi.text.strip() + '')
etiket.show()
i+=1
satirBoyu += 10
def boluolay_manset(self):
boluolay_manset=QLabel(self)
boluolay_manset.setText("DİĞER HABERLER")
boluolay_manset.setGeometry(100,180,500,70)
boluolay_manset.show()
satirBoyu=140
i=1
for manset in soup.find_all("ul",class_="news marginTen"):
for diger_haber in manset("a",class_="title"):
etiket = QLabel(self)
etiket.setOpenExternalLinks(True)
etiket.setGeometry(100,satirBoyu,500,satirBoyu+50)
etiket.setText(''+str(i) + ". " + diger_haber.text.strip() + '')
etiket.show()
i+=1
satirBoyu += 10
def boluolay_koseyazilari(self):
boluolay_ky=QLabel(self)
boluolay_ky.setText("KÖŞE YAZARLARI")
boluolay_ky.setGeometry(100,450,500,70)
boluolay_ky.show()
webpage=urllib.request.urlopen('http://www.boluolay.com/yazarlar.html')
soup = bs4.BeautifulSoup(webpage, 'html.parser')
satirBoyu=320
i=1
for manset in soup.find_all("div",id="yazark"):
for mansetb in manset.find_all("b"):
for yazar_konu in manset("span"):
ab=yazar_konu
etiket = QLabel(self)
etiket.setOpenExternalLinks(True)
etiket.setGeometry(100,satirBoyu,500,satirBoyu+50)
etiket.setText(''+str(i) + ". " + ab.text.strip() + '')
etiket.show()
i+=1
satirBoyu += 10
uygulama = QApplication(sys.argv)
pencere = ButonluPencere()
pencere.show()
uygulama.exec_()

If you want to click on URLs of your QLabel, then you would need to set a few more properties for it (aside from setOpenExternalLinks) like setTextInteractionFlags to Qt::TextBrowserInteraction and setTextFormat to Qt::RichText
Edit (add these lined to every label that you need to click URL on etiket as example):
etiket.setOpenExternalLinks(True)
etiket.setTextInteractionFlags(Qt.TextBrowserInteraction)
etiket.setTextFormat(Qt.RichText)

QLabel is not clickable generally, but you can overload QLabel.mousePressEvent or QLabel.mouseReleaseEvent method to recognize clicked signal; like this:
class Form(QWidget):
def __init__(self):
QDialog.__init__(self)
self.t=QLabel('Click Me',self)
self.t.mousePressEvent=self.labelClick
def labelClick(self,e):
if e.button() == Qt.LeftButton:
print('Clicked')
QLabel.mousePressEvent(self.t,e)

Related

How do I connect WindowContextHelpButtonHint to a widget click?

I can add self.setWindowFlags(Qt.Window | Qt.WindowContextHelpButtonHint | Qt.WindowCloseButtonHint) to the constructor of my QMainWindow which adds the '?' button. Now I want to add contextual help information to virtually all UI components. How do I connect a click on the '?' button and then a click on some ui element (say a qlistview) such that a help message pops up?
Below is part of my program stripped to make it easy. How do I make it such that when the user clicks the '?' and then either a QDoubleSpinBox or the QListView or any of the QPushButtons that a help message displays?
I have searched for this but it seems the vast amount of questions and answers are about how to remove the '?' button or how to add it. None actually deal with how to alter the button's behaviour.
I've also tried using setInputMethodHints() to assign hints to ui components but this method doesn't accept custom strings as I assumed it would.
Btw: I also would like the '?' button to not replace the minimization button. I have yet to figure out how to achieve this either.
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
APPNAME = 'Mesoscale Brain Explorer'
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setWindowTitle(APPNAME)
self.sidebar = Sidebar()
self.setWindowFlags(Qt.Window | Qt.WindowContextHelpButtonHint | Qt.WindowCloseButtonHint)
self.setup_ui()
def setup_ui(self):
self.pl_frame = QFrame()
splitter = QSplitter(self)
self.enable = lambda yes: splitter.setEnabled(yes)
splitter.setHandleWidth(3)
splitter.setStyleSheet('QSplitter::handle {background: #cccccc;}')
splitter.addWidget(self.sidebar)
splitter.addWidget(self.pl_frame)
self.setCentralWidget(splitter)
self.menu = self.menuBar()
m = self.menu.addMenu('&File')
a = QAction('&New project', self)
a.setShortcut('Ctrl+N')
a.setStatusTip('Create new project')
m.addAction(a)
a = QAction('&Open project', self)
a.setShortcut('Ctrl+O')
a.setStatusTip('Open project')
m.addAction(a)
a = QAction("&Quit", self)
a.setShortcut("Ctrl+Q")
a.setStatusTip('Leave The App')
a.setIcon(QIcon('pics/quit.png'))
m.addAction(a)
about_action = QAction('&About ' + APPNAME, self)
about_action.setStatusTip('About ' + APPNAME)
about_action.setShortcut('F1')
m = self.menu.addMenu('&Project')
m.setEnabled(False)
a = QAction("&Close", self)
a.setStatusTip('Close project')
m.addAction(a)
self.project_menu = m
help_menu = self.menu.addMenu('&Help')
help_menu.addAction(about_action)
class Sidebar(QWidget):
open_pipeconf_requested = pyqtSignal()
open_datadialog_requested = pyqtSignal()
automate_pipeline_requested = pyqtSignal()
x_origin_changed = pyqtSignal(float)
y_origin_changed = pyqtSignal(float)
units_per_pixel_changed = pyqtSignal(float)
def __init__(self, parent=None):
super(Sidebar, self).__init__(parent)
self.x_origin = QDoubleSpinBox()
self.y_origin = QDoubleSpinBox()
self.units_per_pixel = QDoubleSpinBox()
self.setup_ui()
def setup_ui(self):
self.setContentsMargins(4, 6, 5, 0)
vbox = QVBoxLayout()
hbox = QHBoxLayout()
hbox.addWidget(QLabel('Origin:'))
hbox.addWidget(QLabel('Units per pixel:'))
vbox.addLayout(hbox)
hbox2 = QHBoxLayout()
hhbox = QHBoxLayout()
hhbox2 = QHBoxLayout()
hhbox.addWidget(QLabel("X:"))
hhbox.addWidget(self.x_origin)
hhbox.addWidget(QLabel("Y:"))
hhbox.addWidget(self.y_origin)
hhbox2.addWidget(self.units_per_pixel)
hbox2.addLayout(hhbox)
hbox2.addLayout(hhbox2)
vbox.addLayout(hbox2)
self.units_per_pixel.setDecimals(5)
self.units_per_pixel.setMaximum(100000)
self.x_origin.setMaximum(100000)
self.y_origin.setMaximum(100000)
self.pl_list = QListView()
self.pl_list.setIconSize(QSize(18, 18))
self.pl_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.pl_list.setEditTriggers(QAbstractItemView.NoEditTriggers)
vbox.addWidget(QLabel('Pipeline:'))
vbox.addWidget(self.pl_list)
pb = QPushButton('&Automation')
pb.clicked.connect(self.automate_pipeline_requested)
vbox.addWidget(pb)
vbox.addSpacerItem(QSpacerItem(0, 1, QSizePolicy.Minimum, QSizePolicy.Expanding))
pb = QPushButton('&Configure Pipeline')
pb.clicked.connect(self.open_pipeconf_requested)
vbox.addWidget(pb)
pb = QPushButton('&Manage Data')
pb.clicked.connect(self.open_datadialog_requested)
vbox.addWidget(pb)
vbox.setStretch(0, 0)
vbox.setStretch(1, 0)
vbox.setStretch(2, 0)
self.setLayout(vbox)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setApplicationName(APPNAME)
app.setOrganizationName('University of British Columbia')
w = MainWindow()
w.resize(1060, 660)
w.show()
app.exec_()
app.deleteLater()
del w
sys.exit()

How to highlight QTreeWidgetItem text

When the button is clicked I need the tree-item to turn highlighted (editing mode) (see the image below). Currently I have to double-click the item to set it in to highlighted mode. How to achieve this?
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication([])
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.setLayout(QtGui.QVBoxLayout())
tree = QtGui.QTreeWidget()
self.layout().addWidget(tree)
button = QtGui.QPushButton()
button.setText('Add Item')
self.layout().addWidget(button)
button.clicked.connect(self.onClick)
item = QtGui.QTreeWidgetItem()
item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
item.setText(0, 'Item number 1')
tree.addTopLevelItem(item)
def onClick(self):
print 'onClick'
dialog=Dialog()
dialog.show()
app.exec_()
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication([])
class ItemDelegate(QtGui.QItemDelegate):
def __init__(self, parent):
QtGui.QItemDelegate.__init__(self, parent)
def createEditor(self, parent, option, index):
if not index: return
line = QtGui.QLineEdit(parent)
line.setText('Please enter the ')
# line.selectAll()
line.setSelection(0, len(line.text()))
line.setFocus()
return line
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.setLayout(QtGui.QVBoxLayout())
self.tree = QtGui.QTreeWidget()
self.layout().addWidget(self.tree)
button = QtGui.QPushButton()
button.setText('Add Item')
self.layout().addWidget(button)
button.clicked.connect(self.onClick)
self.tree.setColumnCount(3)
delegate=ItemDelegate(self)
self.tree.setItemDelegate(delegate)
for row in range(5):
rootItem = QtGui.QTreeWidgetItem()
self.tree.addTopLevelItem(rootItem)
for column in range(3):
rootItem.setText(column, 'Root %s row %s'%(row, column))
for child_number in range(2):
childItem = QtGui.QTreeWidgetItem(rootItem)
for col in range(3):
childItem.setText(col, 'Child %s row %s'%(child_number, col))
def onClick(self):
rootItem = QtGui.QTreeWidgetItem()
rootItem.setText(0, 'New Item')
rootItem.setFlags(rootItem.flags() | QtCore.Qt.ItemIsEditable)
self.tree.addTopLevelItem(rootItem)
self.tree.openPersistentEditor(rootItem, 0)
rootItem.setSelected(True)
dialog=Dialog()
dialog.show()
app.exec_()

How to implement a tree-based QComboBox

How can I implement a QComboBox that allows you to choose from a tree structure, akin to QTreeView?
I came up with the following class (TreeComboBox) using a two-part recipe at developer.nokia.com (Part 1, Part 2):
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class TreeComboBox(QComboBox):
def __init__(self, *args):
super().__init__(*args)
self.__skip_next_hide = False
tree_view = QTreeView(self)
tree_view.setFrameShape(QFrame.NoFrame)
tree_view.setEditTriggers(tree_view.NoEditTriggers)
tree_view.setAlternatingRowColors(True)
tree_view.setSelectionBehavior(tree_view.SelectRows)
tree_view.setWordWrap(True)
tree_view.setAllColumnsShowFocus(True)
self.setView(tree_view)
self.view().viewport().installEventFilter(self)
def showPopup(self):
self.setRootModelIndex(QModelIndex())
super().showPopup()
def hidePopup(self):
self.setRootModelIndex(self.view().currentIndex().parent())
self.setCurrentIndex(self.view().currentIndex().row())
if self.__skip_next_hide:
self.__skip_next_hide = False
else:
super().hidePopup()
def selectIndex(self, index):
self.setRootModelIndex(index.parent())
self.setCurrentIndex(index.row())
def eventFilter(self, object, event):
if event.type() == QEvent.MouseButtonPress and object is self.view().viewport():
index = self.view().indexAt(event.pos())
self.__skip_next_hide = not self.view().visualRect(index).contains(event.pos())
return False
app = QApplication([])
combo = TreeComboBox()
combo.resize(200, 30)
parent_item = QStandardItem('Item 1')
parent_item.appendRow([QStandardItem('Child'), QStandardItem('Yesterday')])
model = QStandardItemModel()
model.appendRow([parent_item, QStandardItem('Today')])
model.appendRow([QStandardItem('Item 2'), QStandardItem('Today')])
model.setHeaderData(0, Qt.Horizontal, 'Name', Qt.DisplayRole)
model.setHeaderData(1, Qt.Horizontal, 'Date', Qt.DisplayRole)
combo.setModel(model)
combo.show()
app.exec_()

How do I make a QTreeView always sort items of a certain category first?

I would like to display "folders" and "files" in a QTreeView. Folders are meant to be able to contain files, and due to this relationship I wish for folder items to be displayed above file items in the tree view. The view should be sortable. How do I make sure that folder items are displayed above file items at all times in the tree view?
The below code provides an example of a tree view with folder and file items:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
def _create_item(text, is_folder):
item = QStandardItem(text)
item.setData(is_folder, Qt.UserRole)
return item
def _folder_row(name, date):
return [_create_item(text, True) for text in (name, date)]
def _file_row(name, date):
return [_create_item(text, False) for text in (name, date)]
class _Window(QMainWindow):
def __init__(self):
super().__init__()
widget = QWidget()
self.__view = QTreeView()
layout = QVBoxLayout(widget)
layout.addWidget(self.__view)
self.setCentralWidget(widget)
model = QStandardItemModel()
model.appendRow(_file_row('File #1', '01.09.2014'))
model.appendRow(_folder_row('Folder #1', '01.09.2014'))
model.appendRow(_folder_row('Folder #2', '02.09.2014'))
model.appendRow(_file_row('File #2', '03.09.2014'))
model.setHorizontalHeaderLabels(['Name', 'Date'])
self.__view.setModel(model)
self.__view.setSortingEnabled(True)
app = QApplication([])
w = _Window()
w.show()
app.exec_()
A solution is to wrap the model in a QSortFilterProxyModel, and reimplement the proxy's lessThan method to make it so that folder items are always placed before file items:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
def _create_item(text, is_folder):
item = QStandardItem(text)
item.setData(is_folder, Qt.UserRole)
return item
def _folder_row(name, date):
return [_create_item(text, True) for text in (name, date)]
def _file_row(name, date):
return [_create_item(text, False) for text in (name, date)]
class _SortProxyModel(QSortFilterProxyModel):
"""Sorting proxy model that always places folders on top."""
def __init__(self, model):
super().__init__()
self.setSourceModel(model)
def lessThan(self, left, right):
"""Perform sorting comparison.
Since we know the sort order, we can ensure that folders always come first.
"""
left_is_folder = left.data(Qt.UserRole)
left_data = left.data(Qt.DisplayRole)
right_is_folder = right.data(Qt.UserRole)
right_data = right.data(Qt.DisplayRole)
sort_order = self.sortOrder()
if left_is_folder and not right_is_folder:
result = sort_order == Qt.AscendingOrder
elif not left_is_folder and right_is_folder:
result = sort_order != Qt.AscendingOrder
else:
result = left_data < right_data
return result
class _Window(QMainWindow):
def __init__(self):
super().__init__()
widget = QWidget()
self.__view = QTreeView()
layout = QVBoxLayout(widget)
layout.addWidget(self.__view)
self.setCentralWidget(widget)
model = QStandardItemModel()
model.appendRow(_file_row('File #1', '01.09.2014'))
model.appendRow(_folder_row('Folder #1', '01.09.2014'))
model.appendRow(_folder_row('Folder #2', '02.09.2014'))
model.appendRow(_file_row('File #2', '03.09.2014'))
model.setHorizontalHeaderLabels(['Name', 'Date'])
proxy_model = _SortProxyModel(model)
self.__view.setModel(proxy_model)
self.__view.setSortingEnabled(True)
app = QApplication([])
w = _Window()
w.show()
app.exec_()

AttributeError: 'QTextEdit' object has no attribute 'text'

Sometimes I need to make multiple copies of code with incrementing numbers.
In a form I'm coding, I need to make upwards of 12 checkboxes, each of which requires the following code:
self.checkBox1 = QtGui.QCheckBox()
self.checkBox1.setGeometry(QtCore.QRect(20, 20, 70, 17))
self.checkBox1.setObjectName(_fromUtf8("checkBox1"))
The script below enables me to avoid the boring task of manually changing the numbers for each checkbox.
I just copy the 3 lines above into the windows clipboard, and then...
I insert "checkBox" into the first field in the form, "1" into the second field, and 12 into the third field.
When I hit the "ok" button, the 12 sequentially numbered copies of the 3 lines appear in the 4th field in the form.
I hope this provides some help to other people.
Marc
Here's my code:
# -*- coding: latin-1 -*-
"""
duplicate_text_with_incrementing_nos_for_programming_and_paste_to_clipboard.py
Harvest text from clipboard and run functions below, and then paste back to clipboard
"""
import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
from PyQt4.QtCore import (Qt, SIGNAL)
from PyQt4.QtGui import (QApplication, QDialog, QHBoxLayout, QLabel,
QPushButton)
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.initUI()
def initUI(self):
okButton01 = QtGui.QPushButton("OK")
cancelButton01 = QtGui.QPushButton("Cancel")
okButton01.clicked.connect(self.fn_okButton01_clicked)
cancelButton01.clicked.connect(QtCore.QCoreApplication.instance().quit)
self.cancelButton01 = cancelButton01
prefix_label = QtGui.QLabel('Prefix')
digit_label = QtGui.QLabel('Digit')
iterations_label = QtGui.QLabel('Iterations')
clip_label = QtGui.QLabel('Clip')
prefixEdit = QtGui.QLineEdit()
digitEdit = QtGui.QLineEdit()
iterationsEdit = QtGui.QLineEdit()
reviewEdit = QtGui.QTextEdit()
self.prefix_label = prefix_label
self.digit_label = digit_label
self.iterations_label = iterations_label
self.clip_label = clip_label
self.prefixEdit = prefixEdit
self.digitEdit = digitEdit
self.iterationsEdit = iterationsEdit
self.reviewEdit = reviewEdit
hbox01 = QtGui.QHBoxLayout()
hbox01.addWidget(prefix_label)
hbox01.addWidget(prefixEdit)
hbox01.addWidget(digit_label)
hbox01.addWidget(digitEdit)
hbox01.addWidget(iterations_label)
hbox01.addWidget(iterationsEdit)
hbox03 = QtGui.QHBoxLayout()
hbox03.addWidget(clip_label)
hbox03.addWidget(reviewEdit)
self.reviewEdit.setText(fn_getText())
hbox00 = QtGui.QHBoxLayout()
hbox00.addStretch(1)
hbox00.addWidget(okButton01)
hbox00.addWidget(cancelButton01)
vbox0 = QtGui.QVBoxLayout()
vbox0.addLayout(hbox01)
vbox0.addStretch(1)
vbox0.addLayout(hbox03)
vbox0.addStretch(1)
vbox0.addLayout(hbox00)
self.setLayout(vbox0)
self.setGeometry(300, 300, 600, 300) #class PySide.QtCore.QRectF(left, top, width, height) http://srinikom.github.com/pyside-docs/PySide/QtCore/QRectF.html#PySide.QtCore.QRectF
self.setWindowTitle('Duplicate Code Strings W/Increasing Numbers')
self.show()
def fn_okButton01_clicked(self):
prefixEditText = str(self.prefixEdit.text())
digitEditText = str(self.digitEdit.text())
iterationsEditText = str(self.iterationsEdit.text())
nutext = prefixEditText + ' ' + digitEditText + ' ' + iterationsEditText
print 'Line 89: nutext = ' + str(nutext)
original_clip = self.reviewEdit.toPlainText() # PySide.QtGui.QLineEdit.text(), http://srinikom.github.com/pyside-docs/PySide/QtGui/QLineEdit.html
txt2paste2clipbd = fn_duplicate_code_with_increments(texte=str(original_clip), no_of_copies=str(iterationsEditText), string_b4_digits=str(prefixEditText), digits=str(digitEditText))
self.reviewEdit.setPlainText(txt2paste2clipbd)
setWinClipText(txt2paste2clipbd)
#self.deleteLater()
#event.accept() #http://www.qtcentre.org/threads/20895-PyQt4-Want-to-connect-a-window-s-close-button
#self.destroy()
def formm():
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
def fn_getText():
# get text from clipboard
win32clipboard.OpenClipboard()
text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT)
win32clipboard.CloseClipboard()
return text
def setWinClipText(aString):
# Send text to clipboard
import win32clipboard
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(aString)
win32clipboard.CloseClipboard()
def fn_duplicate_code_with_increments(texte, no_of_copies, string_b4_digits, digits):
"""
to do: combine args 2 and 3, and use re module to determine with chars are the digits to increment
"""
import re
import string
i = 0
tempclipDup = texte[:]
temp_instance = ''
accumulator = ''
while i <= int(no_of_copies) - 1:
i +=1
orig_str = string_b4_digits + str(digits)
replact_st = string_b4_digits + str(i)
temp_instance = tempclipDup.replace(orig_str, replact_st)
if len(accumulator) > 2:
accumulator = accumulator + '\n' + temp_instance
else:
accumulator = temp_instance
return accumulator
if 1 == 1:
import os
import sys
import subprocess
import win32clipboard
import win32con
fn_operation_log = ''
arg_sent_2this_script = ''
alternative = 1
if alternative == 1:
formm()
elif alternative == 2:
txt2paste2clipbd = fn_duplicate_code_with_increments(texte=fn_getText(), no_of_copies=3, string_b4_digits='hbox', digits=1)
setWinClipText(txt2paste2clipbd)
The property is called plainText for QTextEdit.
(Contrary to the single line QLineEdit, which has a text property)

Resources