удаление элементов из QComboBox из пользовательского интерфейса
Я пытаюсь настроить пользовательский интерфейс QComboBox таким образом, чтобы пользователь мог удалить элементы из выпадающего списка (без предварительного их выбора).
Фон заключается в том, что я использую QComboBox, чтобы указать, какой файл данных открыт прямо сейчас. Я также использую его в качестве кэша для недавно открытых файлов. Я хотел бы, чтобы пользователь мог удалить записи, которые он больше не хочет иметь в списке. Это может быть либо просто нажав клавишу delete, либо контекстное меню, или что угодно еще. простой в реализации. Я не хочу полагаться на выбор предмета в первую очередь. Аналогичное поведение можно найти в Firefox, где старые кэшированные предложения для поданной записи могут быть удалены.
Я рассматривал подклассы представления списка, используемого QComboBox, однако я не нашел достаточно документации, чтобы начать работу.
Буду признателен за любые подсказки и предложения. Я использую PyQt, но у меня нет проблем с образцами C++.
3 ответов:
Я решил эту проблему, используя код из документации installEventFilter.
//must be in a header, otherwise moc gets confused with missing vtable class DeleteHighlightedItemWhenShiftDelPressedEventFilter : public QObject { Q_OBJECT protected: bool eventFilter(QObject *obj, QEvent *event); }; bool DeleteHighlightedItemWhenShiftDelPressedEventFilter::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); if (keyEvent->key() == Qt::Key::Key_Delete && keyEvent->modifiers() == Qt::ShiftModifier) { auto combobox = dynamic_cast<QComboBox *>(obj); if (combobox){ combobox->removeItem(combobox->currentIndex()); return true; } } } // standard event processing return QObject::eventFilter(obj, event); } myQComboBox->installEventFilter(new DeleteHighlightedItemWhenShiftDelPressedEventFilter);
Вы можете создать специализированный класс, который автоматизирует некоторые процессы, и таким образом экономит время в конечном итоге. Например, в https://phabricator.kde.org/D15693 (для программы с именем Krusader) можно увидеть новый класс
KrHistorComboBox(который наследует от KHistoryComboBox) и его использование; но на этот раз для этого ответа: это версия, которая наследует непосредственно отQComboBox, и один пример ее использования:Файл main.cpp
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }Файл главное окно.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_HФайл mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include "krhistorcombobox.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // Creates a new editable comboBox, and populates it with data KrHistorComboBox *combox; combox = new KrHistorComboBox(this); combox->setEditable(true); QStringList elementsToAdd = {"one", "two", "three"}; combox->insertItems(0, elementsToAdd); } MainWindow::~MainWindow() { delete ui; }Файл krhistorcombobox.h
/***************************************************************************** * Copyright (C) 2018 Shie Erlich <[email protected]> * * Copyright (C) 2018 Rafi Yanai <[email protected]> * * Copyright (C) 2018 Krusader Krew [https://krusader.org] * * * * This file is part of Krusader [https://krusader.org]. * * * * Krusader is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 2 of the License, or * * (at your option) any later version. * * * * Krusader is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * *****************************************************************************/ #ifndef KRHISTORCOMBOBOX_H #define KRHISTORCOMBOBOX_H // QtWidgets #include <QComboBox> /*! A KrHistorComboBox event filter that e.g. deletes the current item when the user presses Shift+Del There was more information in https://doc.qt.io/qt-5/qobject.html#installEventFilter, https://forum.qt.io/post/160618 and https://stackoverflow.com/questions/17820947/remove-items-from-qcombobox-from-ui/52459337#52459337 */ class KHBoxEventFilter : public QObject { Q_OBJECT public: explicit KHBoxEventFilter(QObject *parent = nullptr) : QObject(parent) {} protected: bool eventFilter(QObject *obj, QEvent *event) override; }; //! An event filter for the popup list of a KrHistorComboBox, e.g. it deletes the current item when the user presses Shift+Del class KHBoxListEventFilter : public QObject { Q_OBJECT public: explicit KHBoxListEventFilter(QObject *parent = nullptr) : QObject(parent) {} protected: bool eventFilter(QObject *obj, QEvent *event) override; }; //! A specialized version of a QComboBox, e.g. it deletes the current item when the user presses Shift+Del class KrHistorComboBox : public QComboBox { Q_OBJECT public: explicit KrHistorComboBox(QWidget *parent = nullptr); protected: KHBoxEventFilter boxEF; KHBoxListEventFilter listEF; }; #endif // KRHISTORCOMBOBOX_HФайл krhistorcombobox.cpp
/***************************************************************************** * Copyright (C) 2018 Shie Erlich <[email protected]> * * Copyright (C) 2018 Rafi Yanai <[email protected]> * * Copyright (C) 2018 Krusader Krew [https://krusader.org] * * * * This file is part of Krusader [https://krusader.org]. * * * * Krusader is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 2 of the License, or * * (at your option) any later version. * * * * Krusader is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * *****************************************************************************/ #include "krhistorcombobox.h" // QtCore #include <QEvent> // QtGui #include <QKeyEvent> // QtWidgets #include <QAbstractItemView> bool KHBoxEventFilter::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::KeyPress) { auto keyEvent = static_cast<QKeyEvent *>(event); if (keyEvent->modifiers() == Qt::ShiftModifier && keyEvent->key() == Qt::Key::Key_Delete) { auto box = dynamic_cast<QComboBox *>(obj); if (box != nullptr) { // Delete the current item box->removeItem(box->currentIndex()); return true; } } } // Perform the usual event processing return QObject::eventFilter(obj, event); } bool KHBoxListEventFilter::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::KeyPress) { auto keyEvent = static_cast<QKeyEvent *>(event); if (keyEvent->modifiers() == Qt::ShiftModifier && keyEvent->key() == Qt::Key::Key_Delete) { auto iv = dynamic_cast<QAbstractItemView *>(obj); if (iv->model() != nullptr) { // Delete the current item from the popup list iv->model()->removeRow(iv->currentIndex().row()); return true; } } } // Perform the usual event processing return QObject::eventFilter(obj, event); } KrHistorComboBox::KrHistorComboBox(QWidget *parent) : QComboBox(parent) { installEventFilter(&boxEF); QAbstractItemView* iv = view(); if (iv != nullptr) iv->installEventFilter(&listEF); }Файл krhcexample.pro
#------------------------------------------------- # # Project created by QtCreator 2018-09-22T18:33:23 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = untitled TEMPLATE = app # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ krhistorcombobox.cpp \ mainwindow.cpp HEADERS += \ krhistorcombobox.h \ mainwindow.h FORMS += \ mainwindow.uiФайл mainwindow.ui
<ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow" > <property name="geometry" > <rect> <x>0</x> <y>0</y> <width>400</width> <height>300</height> </rect> </property> <property name="windowTitle" > <string>MainWindow</string> </property> <widget class="QMenuBar" name="menuBar" /> <widget class="QToolBar" name="mainToolBar" /> <widget class="QWidget" name="centralWidget" /> <widget class="QStatusBar" name="statusBar" /> </widget> <layoutDefault spacing="6" margin="11" /> <pixmapfunction></pixmapfunction> <resources/> <connections/> </ui>
Это скриншот выполняемого примера: программа перед нажатием Shift+Del, которая удалит опцию с именем " два "
Примечание: некоторые источники код в настоящем ответе основан на https://doc.qt.io/qt-5/qobject.html#installEventFilter, https://forum.qt.io/post/160618 и хорошая работа пользователя с именем " nwp "в https://stackoverflow.com/a/26976984 (хотя этот ответ не включает код для удаления элемента всплывающего списка, если всплывающий список виден, и у него есть" утечка памяти "(объект построен, но не уничтожен), поэтому, если разработчик добавляет деструктор, например
~DeleteHighlightedItemWhenShiftDelPressedEventFilter() { QTextStream(stdout) << "DESTRUCTED" << endl; }, то разработчик позже видит, что код деструктора никогда не выполняется, и поэтому есть утечки памяти; в настоящее время у меня нет точек stackoverflow, чтобы добавить комментарий в https://stackoverflow.com/a/26976984).
Comments