make Custom QWidget selectable - qt

I'm working on a boardgame and I'm trying to make QWidgets (Rectangles) selectable.
So I have a BoardView (inherited from QWidget) which contains BuildingViews, PlantationViews (both inherited from QWidget). It all shows up on the window, but it is not clickable. How can I make this clickable?

You could try to make a QMouseEvent implementation where the widget ID is forwarded,
something like this:
In the implementation of your widget (e.g. YourWidget.cpp):
YourWidget::MouseReleaseEvent(QMouseEvent *event)
{
emit clickedWithMouse(this); // this is a signal, declared in YourWidget.h
}
In the "main" game file (e.g. Game.cpp):
Game::onButtonClicked(YourWidget* widget) // this is a public slot, you must connect all YourWidgets's clickedWithMouse signals to this slot (in Game object code, e.g. when initialising the board)
{
lastWidget = widget; //save the widget "ID" (lastWidget is a member of class Game)
someFunction(widget); //do something with the widget (if you wish)
}

Related

Show a QWidget after pressing a button

I want to change a QWidget in a QMainWindow dynamically. Therefore, the old widget (if it exists) will be deleted, a new one will be constructed and added to the main window.
The widget (_visualization) is a QMainWindow itself that contains a menu bar and a widget that shows an OSG scene graph.
If I donĀ“t call show() on the new widget, I will only see the menu bar, but not the scene graph.
My goal is to call show(), when the user clicks on a button. The button is connected with the outer QMainWindow (MyQMainWindow).
Unfortunately, when I call show() on _visualization in the connected method, the scene graph will not be shown. In contrast to that, the scene graph will be shown, if I call it in the constructor method (loadVisualization(...)).
MyQMainWindow::MyQMainWindow(QWidget *parent ) :
QMainWindow(parent) {
...
loadVisualization(...);
connect(_ui->nextButton, SIGNAL(clicked()), this, SLOT(showNext()));
...
}
void MyQMainWindow::loadVisualization(QString filePath) {
if (_visualization) {
_heightWidgetLayout->removeWidget(_visualization);
delete _visualization;
}
_visualization= new HeightVisualization(0, filePath);
_visualization->setParent(_mainWindowWidget);
_heightWidgetLayout->addWidget(_visualization);
//_visualization->show(); // will work here
}
void MyQMainWindow::showNext() {
_visualization->show(); // does not work here!
}
I know that QT will call setVisible(...) on the widget. This method first tests some states in QT (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)). If I call show() in showNext(), these tests lead to a return without any change.
Is it a problem with connectors and slots? Is there a possibility to show the widget, when the user clicked on a button?
What I have learned is that it is easy to use stackedWidget.
You can then programmatically change it with this
currentPageIndex = (currentPageIndex + 1) % 3;
ui->stackedWidget->setCurrentIndex(0);
The 3 can be the total pages you have in your stack widget. You can either use currentPageIndex, or you can just create some constants with the page ids like I have done with the 0.

How to use leaveEvent with listView created from QtCreator form?

I am trying to call some function (or slot) when the mouse leaves the space of my QListView (tableView). Normally, you could use the leaveEvent() function. So for example I could write
void MainWindow::leaveEvent(QEvent * event){
qApp->quit();
}
This works as intended. When the mouse leaves the MainWindow widget, the application quits. However, what if I wanted to quit the application when the mouse leaves my QListView object which is INSIDE of my MainWindow widget?
How do I reimplement a function for this QListView when it was created within Qt Creator's form designer?
Here is what I have (unsuccessfully) tried:
void Ui::tableView::leaveEvent(){
qApp->quit();
}
And below, I have tried using leaveEvent() as a signal, and it says leaveEvent is undefined (can you even use events as SIGNALs?)
connect(ui->tableView, SIGNAL(leaveEvent(QEvent *event)), this, SLOT(testSlot()));
Basically, I am trying to call some function when the mouse leaves my tableView which was created with Qt Creator's form designer. The QListView class seems to have a mouseEntered() SIGNAL, but not mouseLeave() SIGNAL.
Subclass QListView and reimplement the leaveEvent (example):
class MyListView : public QListView
{
Q_OBJECT
void MyListView::leaveEvent(QEvent *e){
QListView::leaveEvent(e);
anyOtherAction();
}
}

Qt::WindowStaysOnTopHint widget is always active

I have a main window (QMainWindow) and a widget with flag Qt::WindowStaysOnTopHint that provides auxiliary information and options (let's call it helper). If I work with main window and then click on any other application this window ceases to be active (isActiveWindow() == false). But if I work with the helper first and then I switch to other application/window (not to Main Window) it stays to be active. How can I handle switching from the helper window to other application? Even QApplication::activeWindow() returns true because of this.
.h file:
//! Popup structure that contains listw_popup that shows tips
struct PopupWidget {
PopupWidget(QWidget*);
QWidget *base;
QListWidget *listw_popup;
};
class MainWindow : public QMainWindow
{
...
private :
PopupWidget popup_spec;
...
}
.cpp file:
PopupWidget::PopupWidget(QWidget* parent)
{
base = new QWidget(parent, Qt::SplashScreen | Qt::WindowStaysOnTop);
listw_popup = new QListWidget(base);
}
MainWindow::MainWindow(QWidget *parent) : ... popup_spec(this) ...
{
...
}
When popup_spec.base.show() is called this widget appears. And if I click on this widget (means the widget becomes active) it stays to be active even if I switch to other application.
Ok so if I follow your requirements correctly,
You want you helper widget(which has Qt::WindowStaysOnTopHint) to be hidden when the application loses focus.
You could try something like this:
In your MainWindow.cpp say in the constructor add:
qApp->installEventFilter(this);
and add an event filter in MainWindow.cpp (don't forget to declare in .h as well):
bool MainWindow::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::ApplicationDeactivate)
popup_spec->base->hide();
return QWidget::eventFilter(object, event);
}
This will hide the helper widget when switching apps. If you want the reverse functionality to show the helper widget when application gets activated, In the same event filter check for QEvent::ApplicationActivate and call popup_spec->base->show();

Drag and drop widget outside source application widgets

I have a Qt Desktop aplication which has several top-level widgets. Subwidgets of top-level widgets can be moved between top-level widgets by using drag-and-drop mechanism.
The problem i have now is to drop a sub-widget outside any of existing top-level widgets and create a new top-level widget to contain this one. Lets call this separation.
Can this be done using drag-and-drop? I could not find a way where my dropEvent goes?
Can i want to handle the drop event in my application even if the drop place is not allowed? Maybe a mouse release or something?
I cannot change everything now but also a question for the future. Is docking/undocking a better way to do this?
Regards
Mihai
I found a way to do this. When drag moves outside of the application widgets QDrag object emits a targetChanged signal with 0 parameter.
So i inherited from QDrag and then emit a custom signal in destructor if the target() is null.
The only problem is that the cursor looks like interdiction of drop and this i could not fix because QDrag can only set cursor pixmap for valid actions like Move or Copy or Link
Update:
Here is the inherited class.
class TabDrag: public QDrag
{
Q_OBJECT
public:
explicit TabDrag(QWidget *dragSource);
~TabDrag();
signals:
void tearOff(); /// emit tearOff signal if the QDrag object is destroyed and target was null
};
TabDrag::TabDrag(QWidget *dragSource):QDrag(dragSource)
{
}
TabDrag::~TabDrag()
{
// check if we need to detach this tab
if(!target())
{
emit tearOff();
}
}
The tearOff signal should be connected to whatever you want to happen. In my case i pull out the widget from the tab and change parent to a new window.
Example of usage
void MyTabBar::mouseMoveEvent(QMouseEvent* event)
{
..................
TabDrag * drag = new TabDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(*m_tabPixmap.data());
drag->setHotSpot(QPoint(m_dragStartPos.x() - tabAtRect.x(), m_dragStartPos.y() - tabAtRect.y()));
drag->exec();
connect(drag, SIGNAL(tearOff()), this, SLOT(onTearOff()));
}

Can't Get Touch Inputs in QPixMap(image) in QView

I have a QScene object in QWidget and inside QWidget I have QGraphicsView. I convert images to QPixMap give it to QScene as an element and I defined touch events in QGraphicsView class. In QGraphicsView's creator method I enabled touch events with:
viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
and I am managing touch event by overriding ViewPortEvent method:
bool DicomView::viewportEvent(QEvent *event)
{
if(event->type() == QEvent::TouchBegin)
{
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
.......
return QGraphicsView::viewportEvent(event);
}
PS: DicomView is type of QGraphicsView.
My problem is when I run the application I can get the touch inputs from the view but when get to QView can not get touch inputs from QPixMap. I tried putting the methods inside QScene instead of QGraphicsView but QScene does not have a ViewPortEvent method. What am I supposed to do?

Resources