Skip to content

Qt for Python

For discussion and questions about Qt for Python (PySide & Shiboken)

3.2k Topics 14.3k Posts
  • 0 Votes
    3 Posts
    36 Views
    SGaistS

    Hi,

    Glad you found out and thanks for sharing !

    Would you mind posting the fixed version ? That might be useful to someone in the future.

  • importing PySide6 or shiboken6 removes trace callback

    Solved
    7
    1 Votes
    7 Posts
    128 Views
    B

    @ctismer
    Thanks for fixing the problem.

  • simplest mvc pattern in pyside6

    Unsolved
    2
    0 Votes
    2 Posts
    133 Views
    SGaistS

    Hi,

    Did you already took a look at Qt's model view implementation ?

  • 0 Votes
    6 Posts
    156 Views
    M

    @Shankarlinga-M I did some testing and it seems that the style from QStyleFactory can override the behavior of effects in the combobox's view() and view().viewport()

    You can try printing the available styles and changing them like this:

    print(QStyleFactory.keys()) app = QApplication(sys.argv) app.setStyle(QStyleFactory.create('Windows'))

    It also seems that the QGraphicsDropShadowEffect() expands the bounding box of the widget you apply it to, but doesn't expand the bounding box of the combobox.view()

  • Could not update timestamps for skipped samples.

    Unsolved
    6
    0 Votes
    6 Posts
    99 Views
    SGaistS

    You don't need to be an expert :-)
    You can simply go to the bug reporting system and check there if there's already something about it.

    If not, open a new ticket providing your example and full system information so it is easier to reproduce. Provide the findings you made about the error message and how it can be dealt with.

    If a report already exist, you can check whether it contains all the information required. If not, add yours. You can also vote for it.

    That would already be a good help to improve Qt.

    You are not required to implement a solution, but if you want to take a shot at it, then just try. It's one way to learn and get better at the subject.

    We all started and tried at some point, that's also how you learn :-)

  • QSystemTrayIcon bug for computer system!!!

    Unsolved
    2
    0 Votes
    2 Posts
    38 Views
    jsulmJ

    @LuoMeng This is not the right place to request bug fixes.
    File a bug report here: https://bugreports.qt.io/secure/Dashboard.jspa

  • How to Keep PyQt6 Window Always on Top on macOS

    Unsolved
    4
    0 Votes
    4 Posts
    146 Views
    SGaistS

    I tested your code on 14.7.3 removing all things that would not work such as the label stuff and it behaves correctly with PyQt6 6.7.1 as well as 6.8.1.

    Which version of PyQt6 are you using ?

  • In QMenu, the mouse hover cannot be set

    Unsolved
    1
    0 Votes
    1 Posts
    46 Views
    No one has replied
  • PYQT TABLE WIDGET ABILITES

    Unsolved
    2
    0 Votes
    2 Posts
    36 Views
    SGaistS

    Hi and welcome to devnet,

    What exactly are you after ?
    Did you already went through the documentation of the corresponding class ?
    Did you check the examples using it ?

  • Unable to make use of QBoundingVolume

    Unsolved
    1
    0 Votes
    1 Posts
    38 Views
    No one has replied
  • 0 Votes
    2 Posts
    52 Views
    F

    You can try to specify QwtSeriesStore as <custom-type name /> with generate="no" and see what happens. But maybe wrapping is better.

  • 0 Votes
    2 Posts
    116 Views
    D

    On Stack Overflow, my question was closed due to "debugging details." I made a bunch of changes based on the comments to that questions and have a smaller example that strips out the thumbnail generation but still has the same issue.

    https://stackoverflow.com/questions/79504092/with-pyqt6-calling-setcurrentindex-and-scrollto-is-inconsistant-with-a-custom-ql

    Here's the new minimal example if anyone wants to take a stab at it:

    import sys from os import listdir from os.path import isfile, join, basename from functools import lru_cache from queue import Queue, Empty from random import shuffle from typing import Optional from PyQt6 import QtCore from PyQt6.QtCore import QSize, Qt, pyqtSlot, QModelIndex, QAbstractListModel, QVariant, QThread, pyqtSignal from PyQt6.QtGui import QImage, QPixmap from PyQt6.QtWidgets import QApplication, QListView, QAbstractItemView, QListWidget, QWidget, QStyle, QMainWindow class ThumbLoaderThread(QThread): thumbnail_loaded = pyqtSignal(str, QImage) def __init__(self): super().__init__() self.thumbnail_queue = Queue() self.error_icon = QWidget().style().standardIcon(QStyle.StandardPixmap.SP_DialogCancelButton).pixmap(250, 250).toImage() def add_thumbnail(self, filename: str): self.thumbnail_queue.put(filename) def run(self) -> None: print('Starting Thumbnailer Thread') while not self.isInterruptionRequested(): try: filename = self.thumbnail_queue.get(timeout=1) thumb = self.__load_thumb(filename) if thumb: self.thumbnail_loaded.emit(filename, thumb) else: self.thumbnail_loaded.emit(filename, self.error_icon) except Empty: ... @lru_cache(maxsize=5000) def __load_thumb(self, filename): print(f'Loading Thumbnail For {filename}') # In the real application, I use openCV to create a thumbnail here # For right now, we're just using a standard image return QWidget().style().standardIcon(QStyle.StandardPixmap.SP_FileIcon).pixmap(250, 250).toImage() class FileListModel(QAbstractListModel): numberPopulated = pyqtSignal(int) def __init__(self, dir_path: str): super().__init__() self.thumbnail_thread = ThumbLoaderThread() self.thumbnail_thread.thumbnail_loaded.connect(self.thumbnail_generated) self.thumbnail_thread.start() self.files = [] self.loaded_file_count = 0 self.set_dir_path(dir_path) def thumbnail_generated(self, filename: str, thumbnail: QImage): idx = self.index_for_filename(filename) if idx >= 0: q_idx = self.createIndex(idx, 0) self.files[idx]['thumbnail'] = QPixmap.fromImage(thumbnail) self.dataChanged.emit(q_idx, q_idx) def index_for_filename(self, filename) -> int: for index, item in enumerate(self.files): if item.get('filename') == filename: return index return -1 def rowCount(self, parent: QModelIndex = QtCore.QModelIndex()) -> int: return 0 if parent.isValid() else self.loaded_file_count def set_dir_path(self, dir_path: str): self.beginResetModel() self.files = [] self.loaded_file_count = 0 only_files = [f for f in listdir(dir_path) if isfile(join(dir_path, f))] # The full program has sorting # In this minimal example, we'll just shuffle the order shuffle(only_files) for f in only_files: vid = join(dir_path, f) self.files.append({'filename': vid, 'thumbnail': None}) self.endResetModel() def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole): if not index.isValid(): return QVariant() if index.row() >= len(self.files) or index.row() < 0: return QVariant() filename = self.files[index.row()]['filename'] thumbnail = self.files[index.row()]['thumbnail'] if role == Qt.ItemDataRole.DisplayRole: return QVariant(basename(filename)) if role == Qt.ItemDataRole.DecorationRole: if thumbnail: return thumbnail else: self.thumbnail_thread.add_thumbnail(filename) return QWidget().style().standardIcon(QStyle.StandardPixmap.SP_BrowserReload) if role == Qt.ItemDataRole.SizeHintRole: return QSize(250, 250 + 25) return QVariant() def fetchMore(self, parent: QModelIndex) -> None: if parent.isValid(): return remainder = len(self.files) - self.loaded_file_count items_to_fetch = min(100, remainder) if items_to_fetch <= 0: print("No More Items to Fetch") return print(f'Loaded Items: {self.loaded_file_count} / Items to Fetch: {items_to_fetch}') self.beginInsertRows(QModelIndex(), self.loaded_file_count, self.loaded_file_count + items_to_fetch - 1) self.loaded_file_count += items_to_fetch self.endInsertRows() self.numberPopulated.emit(items_to_fetch) def get_file_index(self, filename: str) -> Optional[int]: for i, file in enumerate(self.files): if file['filename'] == filename: return i def canFetchMore(self, parent: QModelIndex) -> bool: if parent.isValid(): return False can_fetch = self.loaded_file_count < len(self.files) return can_fetch class MediaBrowser(QListView): def __init__(self, dir_path): super().__init__() self.setLayoutMode(QListView.LayoutMode.Batched) self.setBatchSize(10) self.setUniformItemSizes(True) self.current_directory = dir_path self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) self.setViewMode(QListWidget.ViewMode.IconMode) self.setResizeMode(QListWidget.ResizeMode.Adjust) self.setIconSize(QSize(250, 250)) self.file_list_model = FileListModel(dir_path) self.setModel(self.file_list_model) self.selectionModel().selectionChanged.connect(self.selection_change) self.current_file = None def mousePressEvent(self, event): """Prevent context menu from also selecting a file""" if event.type() == QtCore.QEvent.Type.MouseButtonPress: if event.button() == Qt.MouseButton.RightButton: # In our minimalistic example, right click # Means we will shuffle self.chdir(self.current_directory) if self.current_file: idx = self.model().get_file_index(self.current_file) print(f'Attempting to select and scroll to {self.current_file} at index {idx}') q_idx = self.model().createIndex(idx, 0) if not q_idx.isValid(): print('Index is invalid') self.setCurrentIndex(q_idx) self.scrollTo(q_idx) else: super(MediaBrowser, self).mousePressEvent(event) def chdir(self, directory: str): print(f'Change Directory {directory}.') self.current_directory = directory self.load_files(directory) @pyqtSlot() def selection_change(self): selected = self.selectionModel().selectedIndexes() if len(selected) != 1: print(f'Invalid Selection {selected}') else: s = selected[0] print(f'Item Selection {s}') self.current_file = self.get_model_filename(s.row()) def showEvent(self, event): super().showEvent(event) QApplication.processEvents() def all_files(self): return self.file_list_model.files def get_model_filename(self, index): return self.all_files()[index]['filename'] def load_files(self, dir_path): try: self.file_list_model.set_dir_path(dir_path) except PermissionError as e: print(f'{e.strerror}') class MainWindow(QMainWindow): def __init__(self): super().__init__() browser = MediaBrowser("/tmp/media") self.setCentralWidget(browser) def main(): app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec()) if __name__ == '__main__': main()
  • Using aiohttp with QtAsyncio

    Unsolved
    10
    0 Votes
    10 Posts
    1k Views
    F

    For the record, there is https://bugreports.qt.io/browse/PYSIDE-2713 . Contributions for this would be very welcome.

  • Cannot pip install pyside6_ds?

    Unsolved
    1
    0 Votes
    1 Posts
    70 Views
    No one has replied
  • 0 Votes
    1 Posts
    55 Views
    No one has replied
  • Why does PySide6 need glibc 2.39 since 6.8.1 on aarch64?

    Unsolved
    2
    0 Votes
    2 Posts
    94 Views
    SGaistS

    Hi and welcome to devnet,

    If memory serves well, Ubuntu is used to build Qt for ARM. It has that more recent version of glibc.

  • using qt designer to connect a widget to a method

    Unsolved
    4
    0 Votes
    4 Posts
    140 Views
    SGaistS

    You're welcome !

    I'll put it in a different way: it gives you more control and it's also easier to reason about when reading the code.

    In any case, since you have the answer you sought, please mark the thread as solved using the Topic Tools button or the three dotted menu beside the answer your deem correct so other forum users may know a solution has been found :-)

  • readyRead signal not activating while using QSerialProt

    Solved
    5
    0 Votes
    5 Posts
    177 Views
    jsulmJ

    @Adar70 said in readyRead signal not activating while using QSerialProt:

    I don't know how to make it more robust

    Don't rely on the number of times readyRead is emitted. Instead accumulate the received data until you received all you expect to receive.

  • Using Signals in QGraphicsItem

    Solved
    25
    0 Votes
    25 Posts
    868 Views
    SGaistS

    @JonB I misread the code !

    We are in the territory where your solution (using __init__) is the way to go. Multiple inheritance in Python is quite tricky...

    QObject expects an optional parent parameter which is not given here but it's not expecting the parameters for the QGraphicsLineItem constructor hence the failure. You can try to use the kwargs trick however it won't work either as it's not part of any of the method signature and thus can't work either.

  • How to structure this project?

    Solved
    8
    0 Votes
    8 Posts
    301 Views
    D

    That is great. Thank you very much for your time and help.

    Would you have any (open source) pyqt projects you would recommend to look at and learn from?

    I've got a couple of good books but they usually have small examples focused on specific topics, not complete projects. I'm currently mostly looking at how https://github.com/dietervansteenwegen/serial-tool is set up and try to understand and copy (if it makes sense) that.