I make a simple window with wxwidgets. How can I change the border?
Also how can I call the destroy function(OnClose) with the right arrow button press?
#include <wx/wx.h>
class _Frame: public wxFrame
{
public:
_Frame(wxFrame *frame, const wxString& title);
private:
void OnClose(wxCloseEvent& event);
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(_Frame, wxFrame)
END_EVENT_TABLE()
_Frame::_Frame(wxFrame *frame, const wxString& title)
: wxFrame(frame, -1, title)
{}
void _Frame::OnClose(wxCloseEvent &event)
{
Destroy();
}
class _App : public wxApp
{
public:
virtual bool OnInit();
};
IMPLEMENT_APP(_App);
bool _App::OnInit()
{
_Frame* frame = new _Frame(0L, _("wxWidgets Application Template"));
frame->Show();
return true;
}
To close the window on right-arrow you need to trap EVT_CHAR or EVT_KEY_DOWN like so:
header file:
void OnChar(wxKeyEvent& event);
source file:
void _Frame::OnChar(wxKeyEvent& event)
{
if (event.GetKeyCode() == WXK_RIGHT)
{
wxCommandEvent close(wxEVT_CLOSE_WINDOW);
AddPendingEvent(close);
}
event.Skip();
}
BEGIN_EVENT_TABLE(_Frame, wxFrame)
EVT_CHAR(_Frame::OnChar)
END_EVENT_TABLE()
Changing the border (by setting a different wxBORDER_XXX style) doesn't work for all windows/under all platforms after the initial window creation so you'd better recreate the window if you really, really need to do this.
Related
I have created following dialog using QT designer form class
#ifndef DLG_GAMMA_H
#define DLG_GAMMA_H
#include <QDialog>
namespace Ui {
class Dlg_Gamma;
}
class Dlg_Gamma : public QDialog
{
Q_OBJECT
public:
explicit Dlg_Gamma(QWidget *parent = nullptr);
~Dlg_Gamma() override;
private slots:
void on_horizontalSlider_valueChanged(int value);
void on_saveButton_clicked();
void on_discardButton_clicked();
void on_resetButton_clicked();
signals:
void savechanges(QString filter);
void discardchanges();
void reset();
private:
Ui::Dlg_Gamma *ui;
bool eventFilter(QObject *target, QEvent *event) override;
void closeEvent(QCloseEvent *dlg) override;
bool close_X;
};
#endif // DLG_GAMMA_H
.cpp
bool Dlg_Gamma::eventFilter(QObject *target, QEvent *event)
{
qDebug() << event->type();
}
However, clicking on help button, does not trigger any event.
Has anybody faced this issue before ?
Does anybody know solution ?
bool MyDialog::event(QEvent *e)
{
// reimplement event processing
if(e->type()==QEvent::WhatsThisClicked)
{
QWhatsThisClickedEvent ce = static_cast<QWhatsThisClickedEvent>(e);
....
return true;
}
return QDialog::event(e);
}
This is the event catcher.
To use event filter you need to install it:
installEventFilter(this) in the constructor of the Dialog.
You need to install eventFilter on your 'help button' when using eventFilter.
You need to insert kind of code below in the constructor of the 'Dlg_Gamma'
ui->helpButton->installEventFilter(this)
For more information, Please refer to the information below.
https://doc.qt.io/qt-5/eventsandfilters.html
I would like to emit a signal when hovering a QLabel with the mouse in QT.
Is it possible ?
If not, how can I do it ?
Thanks.
You can do hover handling without subclassing of QLabel. Try next code sample for it:
void LabelHoverHandler::attach(QLabel *label)
{
label->setAttribute(Qt::WA_Hover, true);
label->installEventFilter(this);
}
bool LabelHoverHandler::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::HoverEnter)
{
emit signalMouseHover(dynamic_cast<QLabel*>(obj) );
qDebug() << "HoverEnter";
}
return false;
}
LabelHoverHandler header file:
class LabelHoverHandler : public QObject
{
Q_OBJECT
public:
LabelHoverHandler(QObject *parent);
virtual ~LabelHoverHandler() {};
void attach(QLabel *label);
protected:
bool eventFilter(QObject *obj, QEvent *event);
signals:
void signalMouseHover(QLabel*);
};
Simply create an instance of LabelHoverHandler and call method attach() with a needed label as a parameter.
A possible implementation:
// mylabel.h
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
class MyLabel : public QLabel
{
Q_OBJECT
public:
MyLabel();
~MyLabel();
protected:
virtual void enterEvent(QEvent *ev);
virtual void leaveEvent(QEvent *ev);
private:
bool hover;
};
#endif // MYLABEL_H
and:
// mylabel.cpp
#include "mylabel.h"
#include <QEvent>
MyLabel::MyLabel()
{
hover = false;
setAttribute(Qt::WA_Hover, true);
}
MyLabel::~MyLabel()
{
}
void MyLabel::enterEvent(QEvent *ev)
{
if (!hover){
hover = true;
setText("Send signal here");
}
QLabel::enterEvent(ev);
}
void MyLabel::leaveEvent(QEvent *ev)
{
if (hover){
hover = false;
setText("Mouse leave area");
}
QLabel::leaveEvent(ev);
}
I have some project where I'm interested in using of QML ui.
But it is not enough for us to use standart Qt rendering sistem, I must try to repaint all ui elements every frame, not only in QCoreApplication::processEvents().
It's requered because it is some DirectX render in background of ui.
In this case I found the way to render widgets only using QWidget::render() function, but this method uses CPU instead of GPU, so it is too slow and is't correct at all.
So, what I have:
I have QApplication integrated into my application's loop.
Signals/Slots system works fine and process events is called right
way.
Own render system with DirectX11, that i use to render other
graphics.
I need redraw (update) qt (QML) ui every frame using
DirectX, or maybe angle, but every frame of render.
Already existing code example:
In this example reimplemented widget is app's main window and used like context of DirectX render.
header:
#ifndef _QTD3DCONTEXTWIDGET_
#define _QTD3DCONTEXTWIDGET_
#include <QtWidgets/QWidget>
#include <QtQuick/QQuickView>
#include <QtQuickWidgets/QQuickWidget>
#include <QtQml/qqml.h>
#include <QtWidgets/QPushButton>
#include <QtGui/QPaintEngine>
#include <QtGui/QPaintDevice>
class QtGfxPaintEngine : public QPaintEngine
{
public:
QtGfxPaintEngine(PaintEngineFeatures caps = PaintEngineFeatures());
virtual bool begin(QPaintDevice *pdev);
virtual bool end();
//virtual void drawEllipse(const QRectF &rect);
//virtual void drawEllipse(const QRect &rect);
virtual void drawImage(const QRectF &rectangle,
const QImage &image,
const QRectF &sr,
Qt::ImageConversionFlags flags = Qt::AutoColor);
virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
virtual void drawPoints(const QPointF *points, int pointCount);
virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
virtual void drawRects(const QRectF *rects, int rectCount);
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
virtual void drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p);
// default implementation used
//virtual void drawLines(const QLineF *lines, int lineCount); //not
//virtual void drawLines(const QLine *lines, int lineCount);
//virtual void drawPath(const QPainterPath &path);
//virtual void drawPoints(const QPoint *points, int pointCount);
//virtual void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
//virtual void drawRects(const QRect *rects, int rectCount);
virtual Type type() const;
virtual void updateState(const QPaintEngineState &newState);
private:
int getClosestPowOfTwo(QSize& size);
};
class QtD3DContextWidget : public QWidget
{
Q_OBJECT
public:
QtD3DContextWidget(QWidget* parent = nullptr);
virtual ~QtD3DContextWidget() = default;
virtual QPaintEngine* paintEngine() const;
virtual void paintEvent(QPaintEvent* event);
void mousePressEvent(QMouseEvent *event) override;
QQuickWidget* containerWidget;
QPushButton* widg;
QtGfxPaintEngine* mPaintEngine;
private:
};
#endif // !_QTD3DCONTEXTWIDGET_
cpp, without draw functions (they are implemented with DirectX and works fine):
QtD3DContextWidget::QtD3DContextWidget(QWidget* parent /*= nullptr*/)
: QWidget(parent, Qt::MSWindowsOwnDC)
{
mPaintEngine = new QtGfxPaintEngine(QPaintEngine::AllFeatures);
QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
setAttribute(Qt::WA_NativeWindow, true);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_UpdatesDisabled, true);
setAttribute(Qt::WA_TransparentForMouseEvents);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_OpaquePaintEvent, true);
containerWidget = new QQuickWidget(this);
containerWidget->setAttribute(Qt::WA_TranslucentBackground, true);
containerWidget->setAttribute(Qt::WA_OpaquePaintEvent, true);
containerWidget->setAttribute(Qt::WA_NoSystemBackground, true);
containerWidget->setClearColor(Qt::transparent);
QString sourceUi = QCoreApplication::applicationDirPath() + "/qtui/test.qml";
containerWidget->setSource(QUrl::fromLocalFile(sourceUi));
containerWidget->move(0, 0);
resize(1280, 720);
widg = new QPushButton("test", this);
//widg->setBackgroundRole(QPalette::WindowText);
widg->resize(50, 50);
widg->move(600, 300);
widg->show();
show();
setVisible(true);
//wrapper->show();
}
QPaintEngine* QtD3DContextWidget::paintEngine() const
{
return mPaintEngine;
}
void QtD3DContextWidget::paintEvent(QPaintEvent* event)
{
}
QtGfxPaintEngine::QtGfxPaintEngine(PaintEngineFeatures caps /*= PaintEngineFeatures()*/)
: QPaintEngine(caps)
{}
QPaintEngine::Type QtGfxPaintEngine::type() const
{
return QPaintEngine::Direct3D;
}
void QtGfxPaintEngine::updateState(const QPaintEngineState &newState)
{}
and in render ui method:
QPainter painter(w);
painter.setBrushOrigin(w->containerWidget->pos());
w->containerWidget->render(&painter);// , w->widg->pos());// , w->widg->rect());// , QWidget::DrawChildren);
painter.end();
that's works fine but using CPU.
What i try it's to replace it with
w->repaint();
so entire widget is repainted, but not every frame, and in this case ui is "blinking" and widget try to repain it's background not as transparent, but with white color.
Or replace with
w->containerWidget->repaint();
and nothing is happends.
trying to call QApplication::process events just after w->repaint() don't make sence, as i can see.
and ofcourse i have comented setAttribute(Qt::WA_UpdatesDisabled, true); if i try to refresh widget in this manner.
PS: sorry for my english)))
If you want to render all Qt content through a central renderer then you might be better of implementing your own QPA (Qt Platform Abstraction) plugin, based on or derived from the normal Windows QPA plugin.
Then you can (a) handout your paint device implementation from there and not need any application side code and potentially use something like ANGLE to get the QtQuick scene graph rendered via Direct3D
I need to override event wm_lbuttonup of CMFCRibbonSlider class
class CMyRibbonSlider : public CMFCRibbonSlider
{
public:
virtual void OnLButtonUp(CPoint point); // need this event handler!
};
void CMyRibbonSlider::OnLButtonUp(CPoint point)
{
AfxMessageBox(_T("Works!"))
return;
}
Use CMyRibbonSlider object in MainFrame class
class CMainFrame : public CMDIFrameWndEx
{
....
CMyRibbonSlider* SliderLine;
}
When CMFCRibbonSlider control apears and I click left mousebutton, nothing happens. What do I do wrong?
EDIT:
initialization
CArray<CMFCRibbonBaseElement*, CMFCRibbonBaseElement*> ar;
m_wndRibbonBar.GetElementsByID(ID_SLIDER2, RibbonElementsArray);
m_wndRibbonBar.GetElementsByID(ID_START_BTN, ar);
RibbonElementsArray.Append(ar);
m_wndRibbonBar.GetElementsByID(ID_STOP_BTN, ar);
RibbonElementsArray.Append(ar);
m_wndRibbonBar.GetElementsByID(ID_SLIDER_LINE, ar); //HERE!
RibbonElementsArray.Append(ar);
m_wndRibbonBar.GetElementsByID(IDC_STATIC_TT, ar);
RibbonElementsArray.Append(ar);
Slider = DYNAMIC_DOWNCAST(CMFCRibbonSlider, RibbonElementsArray[0]);
btnStart = DYNAMIC_DOWNCAST(CMFCRibbonButton, RibbonElementsArray[1]);
btnStop = DYNAMIC_DOWNCAST(CMFCRibbonButton, RibbonElementsArray[2]);
SliderLine = (CMyRibbonSlider*)DYNAMIC_DOWNCAST(CMFCRibbonSlider, RibbonElementsArray[3]); //and HERE!
TmpLable = DYNAMIC_DOWNCAST(CMFCRibbonLabel, RibbonElementsArray[4]);
also I have these event handlers in Mainframe class and they work:
ON_UPDATE_COMMAND_UI(ID_SLIDER_LINE, &CMainFrame::OnUpdateSliderLine)
ON_COMMAND(ID_SLIDER_LINE, &CMainFrame::OnSliderLine)
SliderLine->GetPos() also returns right slider position, so I think initialization is right...
It is seem like the CMFCRibbonSlider control isn't added correctly to CMFCRibbonPanel and therefore CMainFrame class does not expose slider’s messages through message map.
Try to use a method described in the following article:
Walkthrough: Creating a New Ribbon Application By Using MFC
The code will be look like below.
MyRibbonSlider.h
#include "afxribbonslider.h"
#pragma once
class CMyRibbonSlider : public CMFCRibbonSlider
{
DECLARE_DYNCREATE(CMyRibbonSlider)
public:
CMyRibbonSlider();
CMyRibbonSlider(UINT nID, int nWidth = 100);
// Implementation
public:
virtual ~CMyRibbonSlider();
virtual void OnLButtonUp(CPoint point);
};
MyRibbonSlider.cpp
#include "stdafx.h"
#include "MyRibbonSlider.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CMyRibbonSlider, CMFCRibbonSlider)
CMyRibbonSlider::CMyRibbonSlider()
{
}
CMyRibbonSlider::CMyRibbonSlider(UINT nID, int nWidth)
: CMFCRibbonSlider(nID, nWidth)
{
}
CMyRibbonSlider::~CMyRibbonSlider()
{
}
void CMyRibbonSlider::OnLButtonUp(CPoint point)
{
TRACE("\nCMyRibbonSlider::OnLButtonUp()");
return;
}
Related declarations in the CMainFrame.h
afx_msg void OnSliderLine();
afx_msg void OnUpdateSliderLine(CCmdUI* pCmdUI);
CMainFrame.cpp
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
...
ON_COMMAND(ID_SLIDER, &CMainFrame::OnSliderLine)
ON_UPDATE_COMMAND_UI(ID_SLIDER, &CMainFrame::OnUpdateSliderLine)
END_MESSAGE_MAP()
void CMainFrame::InitializeRibbon()
{
...
bNameValid = strTemp.LoadString(*your title*);
ASSERT(bNameValid);
CMFCRibbonPanel* pPanelAdvanced = pCategoryHome->AddPanel(strTemp, m_PanelImages.ExtractIcon (*your icon*));
strTemp = _T("Slider");
CMyRibbonSlider* pRibbonSlider = new CMyRibbonSlider(ID_SLIDER);
pPanelAdvanced->Add(pRibbonSlider);
...
}
void CMainFrame::OnSliderLine()
{
// TODO
}
void CMainFrame::OnUpdateSliderLine(CCmdUI* pCmdUI)
{
// TODO
}
Ok, I've been able to get get Drag and Drop working on QGraphicsScene, but not QGraphicsView. My code looks something like this:
class GraphicsView : public QGraphicsView
{
public:
GraphicsView(QGraphicsScene *scene) : QGraphicsView(scene) {}
protected:
void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
event->setAccepted(true);
update();
}
void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
event->setAccepted(true);
update();
}
void dropEvent(QGraphicsSceneDragDropEvent *event)
{
//stuff that never runs...
update();
}
};
Although, this code works perfectly fine with QGraphicsScene inherited instead of QGraphicsView. I also ran the setAcceptDrops(true) function. What am I doing wrong?