Generic transparent Qt widget that can catch clicks? - c++

I've figured out how to use QPainter to draw rectangles. Now I want to have a drawing area where if the user clicks, a 1x1 rectangle is drawn where the mouse pointer is. To accomplish this, I assume I need a transparent Qt widget that supports the clicked() signal.
How do I make such a transparent widget? Or is there something else I can use? Perhaps I can only use the window's clicked() signal?

You don't really need a transparent widget?
All you have to do is implement
protected:
void mousePressEvent(QMouseEvent *event);
for your widget and draw your rectangle.
Take a look at scribble example that comes with Qt.

Related

Scrolling in QGraphicsView

I have problem with scrolling in QGraphicsView.
I've set scene rect in my QGraphicsView subclass:
MyQGraphicsView::MyQGraphicsView{
setSceneRect(0,0,2000,2000)
}
And overloaded paintEvent:
void MyQGraphicsView::paintEvent(QPaintEvent *event){
qDebug()<<"Paint event";
QPainter painter(viewport());
painter.setRenderHint(QPainter::Antialiasing);
paint(painter);
}
void MyQGraphicsView::paint(QPainter &painter){
painter.setPen(Qt::NoPen);
painter.fillRect(QRect(0,0,200,200),Qt::gray);
painter.fillRect(QRect(500,500,1000,100),Qt::green);
painter.setPen(QPen(Qt::white,4,Qt::DashLine));
painter.drawLine(QLine(0,35,200,35));
painter.drawLine(QLine(0,165,200,165));
}
When I scroll the second rectangle is not visible. When I resize window it is. Also when scrolling rectangle is extending in wired way.
How should scrolling be implemened in this case? I've found several topics about scrolling in QGraphicsView but none solves my problem.
QGraphicsView inherits QAbstractScrollArea. So its content is displayed in its internal widget that can be obtained using viewport(). If you want to paint something and be able to scroll it, you need to attach an event filter to viewport widget and process its paintEvent, not view's event.
But you should not do this for QGraphicsView. You're trying to do something terribly wrong. You should not reimplement QGraphicsView::paintEvent just to paint something! It totally devalues its advantages. You need to use QGraphicsScene to add something to the view.

Drag a rectangle over image in Qt

I guess there are lots of ways to achieve this. I have an application in which a video stream is shown over a custom QWidget that I have subclasses from QLabel, and painting frames using QPainter. Given that, is it possible to let the user to drag a rectangle over the image and retrieve the coordinates? The requirement is that the rectangle must be visible during the dragging.
Thanks in advance,
Have a look at QRubberBand. It allows you to place such a rect on top of e.g. a QLabel. The documentation also contains an example how to move and resize the rubberband using the mouse.
the QGraphicsView has the void setRubberBandSelectionMode ( Qt::ItemSelectionMode mode ) but i dont know if the QLabel has some similar feature ...
maybe you have to draw your own rectangle while the user drags the rectangle and catch it on mouserelease
soo long zai
In you widget you could track mouse pressed and released events and track where on the widget the corners of the selection rect are. For drawing the rectangle, I'd take a look at QStyle::drawFocusRect. I think the intent of that is to draw a rect you'd be able to see regardless of what's behind it.
Or perhaps try this:
QStylePainter painter(this);
QStyleOptionFocusRect option;
option.initFrom(this);
option.backgroundColor = palette().color(QPalette::Background);
painter.drawPrimitive(QStyle::PE_FrameFocusRect, option);

QT painting rich text on QGraphicsScene

I am writing very simple vector tool for graphics. I have rich text edited in QTextEditor. I also have class extending QGraphicsScene where all my drawings are. I want to somehow paint text from QTextEditor on this scene? What are my options?
Best Regards!
You can use QPainter::drawtext() method. basically you get a painter of the area you want to draw in and then use this method to draw your text.
QPainter p(this);
p.drawText(rect(), Qt::AlignCenter, "Hello World!");

How to paint with QPainter only after a specific event?

I have a main window with some widgets on it, each needs its own graphic. I would like to use QPainter to draw shapes, lines, etc. on them, but only after a specific event, like the press of a button.
The problem is, if I just create a QPainter in any function, it won't work:
QPainter::setPen: Painter not active
The QPainter methods can only be called inside a paintEvent(QPaintEvent *) function! This raises the following problems:
I have to derive my custom classes for all the widgets I would like to paint on, so I can't use the Designer to place my widgets. This can get frustrating with a large number of widgets.
The widgets redraw themselves after each paint event of the window, like moving it around, or moving other windows in front of it. I do a lot of drawing in those widgets, so they will visibly blink in these cases.
Is there a better and simpler way to solve this? I started to think about just displaying images, and re-manufacturing those images only when the specific buttons are pressed. I doubt that it's the most elegant solution...
You can use custom widgets in the designer: Creating Custom Widgets for Qt Designer.
Qt Designer's plugin-based architecture allows user-defined and third party custom widgets to be edited just like you do with standard Qt widgets.
For your second question, one of the approaches is to create a QPixmap for each of your widgets. When your widget's appearance needs to be changed, you draw in that pixmap (using QPainter's constructor that takes a QPaintDevice - QPixmap is a QPaintDevice).
In your widget's paintEvent function, you simply fill your widget with that "cache" pixmap. This way, you only do the (potentially expensive) painting when it's actually necessary.

painting inside widget in Qt

I created a very simple GUI that has a push button and a "Graphics View" widget from Display Widgets. On pushing the button I want a line to be drawn across the "Graphics View" widget. I have changed the name of the "Graphics View" widget to gv by right-clicking the widget in design view and then selecting change objectName. I am not able to understand how should the line be drawn. I read various texts on Qt that provided information about QPainter, PaintEvent etc. But I got more confused.
Kindly help me with this. A small sample code shall be really helpful for me as I am new to Qt.
A QGraphicsView is meant for displaying instances of QGraphicsItem that are managed by a component called QGraphicsScene. In your case, you'd create a QGraphicsLineItem and add it to the scene, or directly create it as an item of the scene by calling the addLine member function of your QGraphicsScene instance.
All drawing will be done by Qt itself, assuming that you did connect your graphics view and scene properly. Be sure to read The Graphics View Framework, which gives you an overview over how these components work.
You will find code examples of how to manage and display a scene using the graphics view framework here: http://doc.trolltech.com/4.6/examples-graphicsview.html
You can paint into a QPainter
Either override the paintevent and draw there
void MyDisplayWidget::paintEvent(QPaintEvent*)
{
QPainter p(this);
p.setPen(Qt::green);
p.drawText(10,10,"hello");
}
Or draw into a QImage and display that
QImage image = QImage(size);
QPainter p(&image);
p.drawText(10,10,"hello");
// draw or save QImage
You can even use the same draw function taking a QPainter * to draw either direct to the screen or to an image.
first you must knew some information about QPainter to have benefit of it.
QPainter provides highly optimized functions to do most of the drawing GUI programs require. It can draw everything from simple graphical primitives (represented by the QPoint, QLine, QRect, QRegion and QPolygon classes) to complex shapes like vector paths .and we use it to draw on paint devices
then render it to view,and we have alot of qpaint devices like : QWidget, QImage, QPixmap, QPicture, QPrinter, and QOpenGLPaintDevice you can use any one of them depending on your requirements then create QGraphic scene and add you paint device as qgraphic scene item to be shown in qgraphic view.
here is simple code:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
scene=new QGraphicsScene(this); //allocate your scene to your main widget
view=new QGraphicsView(scene,this);//here is your view
pixmap=new QPixmap(QSize(700,700));// paint device
view->resize(700,700);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *e)
{
painter=new QPainter;// create your painter
painter->begin(pixmap);//add painter to your paint device
painter->fillRect(0,0,300,300,Qt::red);//draw rect
painter->setPen(Qt::yellow);
painter->drawLine(0,0,700,700);//draw line
painter->end();
scene->addPixmap(*pixmap);// add your paint device to your scene
view->show();//then show your view
}