QwtLegend inside canvas - qt

I want to have an interactive legend inside my canvas, however I'm having trouble getting it to work. I am using qwt6.1.2 and this version no longer has the option to insert the legend as an "ExternalLegend", but instead has the class qwtPlotLegendItem to handle legends inside the canvas. However when I read the docs I see:
In opposite to QwtLegend the legend item is not interactive.
An external QwtLegend with a transparent background on top the plot
canvas might be another option with a similar effect.
My question is: how do I show an QwtLegend on top of the plot canvas?
In the documentation for QwtPlot I read:
Legends, that are not inserted into the layout of the plot widget need
to connect to the legendDataChanged() signal. Calling updateLegend()
initiates this signal for an initial update.
I have connected the legendDataChanged signal and triggered it by calling updateLegend(), but now I'm stuck on what to do next. Any tips on how to proceed?

Ok I got it to work:
QwtPlot* plot;
// Attach some plots/histograms to the plot.
MyLegend* legend = new MyLegend(plot);
MyLegend ::MyLegend (QwtPlot * pPlot)
: m_pPlot(pPlot)
{
setParent(m_pPlot);
setGeometry(0, 0, 100, 100);
connect(m_pPlot, &QwtPlot::legendDataChanged,
this, &MyLegend ::LegendDataChanged);
m_pPlot->updateLegend();
}
void MyLegend ::LegendDataChanged(const QVariant &itemInfo, const QList< QwtLegendData > &data)
{
updateLegend(itemInfo, data);
}

Related

referencing global variables in a continuous function (p5.js)

it's been years since I coded anything, and now I need to pick up p5.js. As practice I was trying to make a simple drawing program - I want my program to draw in black by default, and switch the color to red when I click on the red rectangle in the corner of the screen. I had the following very sloppy code (I know the mouse-press doesn't exactly line up with the red rectangle, the 'drawing' mechanism isn't the best, etc. I'm just messing around with it atm)
function setup() {
createCanvas(600, 600);
fill ('red');
rect(570,20,5,5);
//creates red rectangle at top right corner of screen
}
var color = 0;
function mousePressed(){
if ( mouseX > 570) {
if( mouseY > 20){
color = 4;
ellipse (10,20,50,50);
}
}
}
function draw() {
stroke(color);
if (mouseIsPressed) {
ellipse(mouseX, mouseY, 1, 1)
//creates colored dot when mouse is pressed
}
}
function keyTyped(){
if (key === 'c'){
clear();
}
}
If I don't use the 'color' variable and instead just set the stroke to 0, I can draw in black well enough. And the mousePressed function seems to work - when I press the rectangle, it draws the ellipse that I put in to test. However, I can't seem to reference var 'color' in my draw function - it's probably a silly problem, but I admit to being stumped! What am I doing wrong?
You have to be careful when naming variables. Specifically, you shouldn't name them the same thing as existing functions!
From the Processing.js help articles:
One of the powerful features of JavaScript is its dynamic, typeless nature. Where typed languages like Java, and therefore Processing, can reuse names without fear of ambiguity (e.g., method overloading), Processing.js cannot. Without getting into the inner-workings of JavaScript, the best advice for Processing developers is to not use function/class/etc. names from Processing as variable names. For example, a variable named line might seem reasonable, but it will cause issues with the similarly named line() function built-into Processing and Processing.js.
Processing.js is JavaScript, so functions can be stored in variables. For example, the color variable is the color() function! So when you create your own color variable, you're overwriting that, so you lose the ability to call the color() function.
The simplest fix is to just change the name of your color variable to something like myColor.

SnapLineSnapResult for objects in JavaFx

Currently I have a project that is being used to draw rooms with lines and images that can be selected by the user by hitting a button representing what they want to add. I.E. if they want a shower a button for shower is pressed and an image appears in a pane. The shower can be resized and moved in the pane. The user also has the ability to use lines to draw objects or walls. The lines can be resized, rotated, or moved. I am now trying to get these objects to interact with each other. Say a user is using lines to make an object, and when the line comes near another object the line being moved snaps to the other object. I have found a 3rd party library that has SnapLineSnapResult but I don't see anything where someone has used it. Is this something that is desktop JavaFX usable, or is it a touch operation and does anyone have code to model or another solution?
SnapLineSnapResult
My code for line that would be useful if I can use this class is as follows:
line.setOnMouseDragged((MouseEvent event1) -> {
// in resize region
if (isInResizeZoneLine(line, event1)) {
// adjust line
line.setEndX(event1.getX());
}
// in movable region
else {
Point2D currentPointer = new Point2D(event1.getX(), event1.getY());
if (bound.getBoundsInLocal().contains(currentPointer)) {
/*--------*/ // potential place for if (near other object to be snapped)
double lineWidth = line.getEndX() - line.getStartX();
line.setStartY(currentPointer.getY());
line.setEndY(currentPointer.getY());
line.setStartX(currentPointer.getX() - lineWidth/2);
line.setEndX(currentPointer.getX() + lineWidth/2);
}
}
});

Need to display the widgets inside my QListWidget with an offset, basically shifted a bit to the right

I have a panel.ui file done using QTDesigner. It's a QFrame class, rectangular shape with few labels on it. And I have a QListWidget class where I insert 3 instances of the panel.ui.
I create a QListWidgetItem and then use List->SetItemWidget(..) to populate my list.
The Result is a list filled with three panels. I was also able to move the panels inside the list using dragDropMode internalMove.
I also tested the ability to shift the panels a bit to the right when I click on them and that worked:
in procedure List::mousePressEvent(QMouseEvent *event)
Panel *child = static_cast<Panel*>(childAt(event->pos()))
...
int y= child->pos().y();
int x = child->pos().x();
child->move (x +10, y); `
Problem: When I run the app and display the list, I want all the panels to be displayed with that 10 offset to the right. So in the List constructor and inside the loop after this->setItemWidget(myPanelItem, myPanel); I try using myPanel->move() like above but it doesn't seem to work.
I run the app, the panels are displayed without my offset ( not sure why?) but when I click on one, it shifts.
move() won't work reliably since the widgets are in a layout. (Well, not a layout as in a QLayout, but the effect is comparable: When any metric in your application changes, e.g. you resize or scroll the list, the widgets are repositioned by the list widget.)
What you can do is wrap your actual widget in a container widget with a layout margin:
QWidget* wrapIntoContainerForOffset(QWidget* widget, int offset /*in pixels*/) {
QWidget* container = new QWidget;
QHBoxLayout* layout = new QLayout(container);
layout->setContentsMargins(/*left=*/ offset, /*others=*/ 0, 0, 0);
layout->addWidget(widget);
return container;
}
Then you add these containers to the listwidget instead.
Have You tried StyleSheets. The QListWidget supports Box model( http://doc.qt.digia.com/qt/stylesheet-customizing.html#box-model ). So You may want to try playing around with margins in the stylesheets.
Style sheet reference: http://doc.qt.digia.com/qt/stylesheet-reference.html

How to remove/clear previously drawn lines before redrawing new lines in Qt?

I am drawing few lines using paintEvent(QPaintEvent * event). Sometime later if I want to draw new lines then the previously drawn lines are not cleared/removed. How could I draw the new lines only, by removing/clearing old lines. Is there any property to clear the previously drawn lines.Please let me know.
void QGraphWidget::paintEvent(QPaintEvent * event)
{
const QRect & rect = event->rect();
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
drawLines(painter, rect);//calling painter.drawLine() inside
}
Thanks...
In my opinion, the correct approach is to clear the area before drawing new lines. This can be achieved either by using the autoFillBackground property as proposed by Stephen Chu, or by calling manually the QPainter::eraseRect() before drawing your lines in the QGraphWidget::paintEvent method.
void QGraphWidget::paintEvent(QPaintEvent * event)
{
const QRect & rect = event->rect();
QPainter painter(this);
painter.eraseRect(rect);
painter.setRenderHint(QPainter::Antialiasing);
drawLines(painter, rect);
}
Another option is to draw "negatively" the lines from the previous call to QGraphWidget::paintEvent. If you store the coordinate of your old lines, you might first draw lines using the background brush and then draw your new lines using the foreground brush. See code sample that might fit into you drawLines method. Note that if you draw something else in your widget, drawing the lines negatively might erase some of the other graphics which is why the first approach, erasing all the GraphWidget area, is better.
// save the current brush
QBrush currentBrush = painter.brush();
// draw the old line with the background brush
painter.setBrush(background());
painter.drawLine(oldLine);
// draw the new line with the current brush
painter.setBrush(currentBrush);
painter.drawLine(newLine);
You want to fill your widget with window background color before redraw. Set autoFillBackground to true after you create the widget and Qt will handle this for you
I don't think there is a specific call to remove the line. If you're repainting the entire area each time paintEvent() function is called you shouldn't see previous lines. If you're not repainting the area, you'll have to draw over the line yourself. This code for instance is drawing a line in a different position each time the method is invoked:
QPainter painter(this);
painter.setBrush(QBrush(Qt::red));
painter.drawRect(rect());
painter.setPen(QPen(Qt::yellow));
static int i = 0;
painter.drawLine(QPointF(i, i), QPointF(i, height() - i));
i++;
but "previous lines" are cleared completely. If you want to keep those you'll have to repaint only a specific area or you'll have to repaint those.
This is one way to delete whole line from QT.
me->setFocus();
int pos;
QTextCursor tc= me->textCursor();
pos=tc.columnNumber();
tc.select(QTextCursor::LineUnderCursor);
QString str=tc.selectedText();
tc.removeSelectedText();
tc.movePosition(QTextCursor::NextBlock,QTextCursor::MoveAnchor);
tc.insertText(str);
tc.insertBlock();
tc.movePosition(QTextCursor::PreviousBlock,QTextCursor::MoveAnchor);
tc.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
me->setTextCursor(tc);
return true;

How to Force a Flex Chart to Redraw During Runtime

I have a column chart that uses a label function to format the vertical axis. I added a button and want the axis (or chart) to redraw when the button is clicked. Right now, the chart axis renders OK only when initially added to the view state.
I have a function that sets various properties after the chart is initially created. In there, I have tried all these:
myChart.verticalAxis.dataChanged();
myChart.validateNow();
myChart.validateDisplayList();
myChart.validateProperties();
myChart.invalidateDisplayList();
myChart.invalidateProperties();
But they do not change the axis formatting. How can I do this?
The MXML code for the axis is:
< mx:LinearAxis id="verticalAxis" labelFunction="vAxisFormat"/>
The label function is:
private function vAxisFormat(labelValue:Number, previousValue:Object, axis:IAxis):String {
axis.getLabelEstimate();
if (_scale == 1){
return currencyFormatter.format(labelValue/_scale);
}else {
return numberFormatter.format(labelValue/_scale);
}
}
Try updating the data provider. This redraws the graph, so all the components.
Example:
ArrayCollection
arr.refresh ();
XML
char.dataprovider = xmlData
regars

Resources