With several widgets sharing the same signal slot (event handler), how do I find out which one has been clicked? - qt

In my project I am using a custom circle-shaped button widget derived from the QWidget class. I have added several of these widgets to a parent widget.
When one of these custom buttons is clicked, how do I find out which one was clicked?
Adding custom button to parent widget:
void ShotViewCTRL::addShot(QString shotNanme)
{
ShotButton *btnShot=new ShotButton(this);
btnShot->shotName=shotNanme;
connect(btnShot,SIGNAL(Shot_Selected()),this,SLOT(SHOT_CLICKED()));
btnShot->CreateButton();
btnShot->show();
}
My parent widget is ShotViewCTRL (inherits from QWidget), the child widget is ShotButton (custom control, inherits from QWidget).
The control is working fine. It's sending sending to parent object. In my problem, I added the same custom control 10 times.
I need to find which control was clicked? Please help me find the solution.
I have referred to the Qt documentation to find the child widget, but I did't understand. Some sample code would be great.

QSignalMapper is what you are looking for. With QSignalMapper, you can add something like an Id (or even a pointer to the QButton itself) as additional data to the signal emittance and you have to adjust your slot so it takes additional data (ID or Pointer).
Then either distinguish in the slot itself by the id you give your objects some virtual function type() so you can distinguish with that or even try casting and catch errors (Tip: don't try the last method, it may work differently on different compiler).

You can use the QObject::Sender function to find which QObject sends the signal. Regarding the first warning in the doc, it's what you are searching for.

you specify different slots for different buttons with same signal.with that you can recognize the different button click

Related

Programmatically Cycle through Tab-Order in QT5

I have a QT5 application in which I have to simulate a tab keypress on an external event i.e. I need to cycle through the taborder list and setFocus on the next element.
I cannot find any method to get the tab-order list programmatically. What would be the best way to do this?
How about a combination of QWidget:: nextInFocusChain() / previousInFocusChain() and setFocus() method or setFocus() slot? (There are some other ways to set focus as well, all cross-linked in the Qt docs.)
nextInFocusChain()and previousInFocusChain() provide public API access to the underlying private members which seem to control the tabbing order. You can see them being used in QWidget::setTabOrder() for example.
Current focus widget could be found with either QWidget::focusWidget() of the parent widget, or QApplication::focusWidget(). Note that QWidget::focusWidget() will also return the first widget in the focus order if none currently have focus. This starting point could be used to build a list of widgets in tab order.

How to enable both internal reordering and external dropping in a Qt widget?

I have created a widget which inherits QListWidget.
My goal is for it to accept files dropped into it from an external file manager, and for the user to be able to reorder the elements in the widget. I can achieve both, but not at the same time.
If I just set
myWidget->setDragDropMode(QListView::InternalMove);
myWidget->setDragEnabled(true);
I can reorder the items within the widget, but I can't drop external items into it.
If I reimplement the dragMoveEvent, dragEnterEvent and dropEvent events, all of them just having acceptProposedAction(); and some debug messages inside them, I can drop external files into my widget, but I can no longer rearrange the items.
Is there a way to have the above two at the same time, or do I have to manage the items myself in the reimplemented functions? If so, how can I know if a dropped item is internal or external, and how can I know from which position it was taken and into which position in the list it was dropped into?
If I parse the mimeData which I got from the event, I can see whether it as a file or a text, and I get "qabstractitemmodeldatalist" if it was an internal item, but it still doesn't give me its position.
I can check event->pos() to know in pixels where the drop has been made, and event->source() to learn about what was dropped there, but is this really best practice, to start calculating pixel values and adding objects "manually"?
The solution was very simple: I just had to call the functions of the parent class at the end of each function I've overridden.
void myWidget::dropEvent(QDropEvent *event)
{
do_stuff_with_received_data(event);
QListWidget::dropEvent(event);
}

Add a delete Button to each Item in QListView

Is it somehow possible to add to each Item in a QListview a Button which is deleting the Object onClick? As shown in the following Picture:
EDIT: As I'm new in QT it would be nice to have some example, to understand it better. And as it seems there are three different Ways? What will be the best? Do use a QAbstractItemView?
Yes. You'll need to use:
QAbstractItemView::setIndexWidget ( const QModelIndex & index, QWidget * widget )
QListView inherits QAbstractItemView and when you're trying to customize list/tree views that's usually the place to look. Be careful though, without a delegate this doesn't scale very well. Check out this thread: http://www.qtcentre.org/threads/26916-inserting-custom-Widget-to-listview
You can also go for a generic approach that can work on variety of containers, including the underlying model of your list view.
Each item in the list has a requestRemoval(Item*) signal and a removeMe() slot, connect the X button to the removeMe() slot in each item constructor, in removeMe() you emit the requestRemoval(this) signal, which is connected to a removeHandler(Item*) slot in your "parent" object upon creation of that item, which receives the pointer of the item which has requests deletion, and removes it from the underlying container being used.
Basically, pressing the remove button causes that particular item to send a pointer of itself to the parent's remove handler which removes that entry.
EDIT: Note that this is a generic approach, as noted in the comments below it can be applied without signals and slots as well, and even though it will work it is not the most efficient solution in your particular case.

Calling a form from a pushbutton using only QtDesigner

I have created a form. I have many 2 push buttons. On clicking on a pushbutton I want to call another custom form. I am using only QtDesigner. I am NOT using QtCreator. Using QtCreator, there are so many examples on how I can do it. But using only QtDesigner 4 there are no examples. I have also tried creating a MainWindow and then having pushbuttons in that. I want to call a new pop up window when I click on a button (which is a custom form). I am using Eclipse CDT as the IDE. I have installed Qt plugin so that I can do both C++ and Qt development. The problem is I cannot use 'Form' to declare my custom form in header file of the mainwindow.
I read in few posts that this is not possible to do using only QtDesigner and also read it can be done using QObject::connect. Please can anyone help me to confirm if we can do it and if yes please can you provide me an example?
Yes, it's definitely possible with C++. You'll need to connect() pushbutton's clicked() signal with a slot in your first form:
connect(pushButton, SIGNAL(clicked()), this, SLOT(show2ndForm()));
The good place to connect is in your first form constructor.
In that slot just show your second form (for example, using QDialog::exec()):
void FirstForm::show2ndForm()
{
static SecondForm *form = 0;
if(!form)
form = new SecondForm(this);
form->exec();
}
You'll probably need to inherit your second form from QDialog to use this method and also create header and source files for your second form.
For modeless form instead of modal, use form->show() instead of exec().
This is not complete possible if you need to customize a slot, but for simple operation where the existing slots are available, you can just use the signal-slot edit as below.
You can select the receiver object and then the correponding slot. I am providing further screenshot to show it is done for customized slots as well.
Right click with your mouse in the middle of the main window and the change signals and slots
Select the change signals and slot option
Use the Add button to add a new slot
Click on the OK button to conirm it once you chose the desired name
In the signal-slot editor double click on the desired object's slot, and it will show the available slots including your new custom slot.
Select your custom slot and you are done from the designer parts. Do not forget to actually implement that in your C++ code.
If you do not need a custom slot, and a built-in will suffice, you can select that off-hand without the previous steps. Those are provided for completeness.

I want to extend dropEvent() (QListWidget), should I completely reimplement it?

I have a QListWidget and I have set it to accept drops, the mode to be DragDrop etc and I can move QListWidgetItems all around the place (inside the QListWidget of course).
I like this behavior and I want it to let it as is, but I also want my QListWidget to accept drops from a QTreeWidget as well. If I attempt to reimplement the dropEvent() of my QListWidget then I lose the default behavior.
Is there any way to just extend the current behavior so as to have both drag-drop between listwidget items and drag-drop from the treewidget to the listwidget or I have to completely re-write both behaviors in my dropEvent() reimplementation?
Thanks a lot for any answers :)
Two ways:
implement a standalone event filter and make it act upon QEvent::Drop. Install it on your original QListWidget. Return false so that the original dropEvent() handler is called afterwards.
inherit from QListWidget, reimplement dropEvent(evt) and as a last statement, call QListWidget::dropEvent(evt);. Your original behavior will be retained.
No.
Subclass QListWidget, reimplement
virtual void QListWidget::dropEvent ( QDropEvent * event )
and explicitly call
QListWidget::dropEvent(event);
whenever you need the default behavior.
How to call a parent class function from derived class function?

Resources