I'm trying to have a custom painting of a pyqtgraph derived Plot widget (the code is found here https://github.com/danielhrisca/asammdf/blob/bfa09d0b46f1b4b98b9ad1d0a0bb90cbb876b43e/asammdf/gui/widgets/plot.py#L4271): since painting a Plot with thousands of curves is very expensive I want to store the result in a QPixmap, then if I have a cursor active (implemented using an InfiteLine (see https://github.com/pyqtgraph/pyqtgraph/blob/6ed7d4fa4762aaa895f7e9b2fb09ec6df4cc793f/pyqtgraph/graphicsItems/InfiniteLine.py#L16) I would first draw the QPixmap on the viewport then on top just the cursor item. This way moving the cursor would not trigger the repaint of all the curves.
The QPixmap looks like this
and this is what happens when I create a cursor and slide it around:
Note that at the end the plot is zoomed out, this causes the reset of the QPixmap and the "native" repaint which produces the correct image with the single vertical line of the cursor.
What could be causing this?
I found the problem to be that the paint events were set to update just certain regions of the viewport instead of the full viewport.
The fix was to set the viewport update mode to full update
self.setViewportUpdateMode(QtWidgets.QGraphicsView.FullViewportUpdate)
Related
While using Delphi Seattle 10 and Steema TeeChart Pro VCL FMX 2016.18, I am looking to Highlight a Selection of a Line Graph (multiple series) in the way that Zooming allows / makes a square around a highlighted selection of a Line Graph to indicate which part of it to zoom into (as long as the onmousedown action is in progress).
The purpose of this would be to allow the selection to remain highlighted while the mouse is no longer being clicked, to potentially "Delete" the highlighted Data points. All I need this for is to obtain the (X0 Y0 X1 Y1) values to possibly obtain the CalcPosPoint(X) and remove all the points inside. The data is currently obtained through a Record Struct (Memory Mapped) file, and it will there for be used to set/check for a property "deleted" to indicate on the next redraw of the graph which rows to completely ignore and which to continue printing.
I hope to be able to do this (select from 1 chart), and have it simultaneously draw on multiple graphs. I have tried to look for an example of this feature through the use of TSelectorTool (FMXTee). One of the pages I found referring to such a tool is Interactive data point selection as well as Multiple selections with Selector Tool
And my second question has to do with TeeCharts directly. Where would I find fmx240.bpl as TeeChart_Pro_Firemonkey_Demo.exe requires this file in order to run? I did manage to copy vcl240.bpl from "Embarcadero\Studio\18.0\bin" and put it into "Embarcadero\Studio\17.0\bin"
[Edited]
I have managed to capture / create a sample code (MVCE) from which I can now select a portion and create a square around a particular sample of graph lines.
The control graph right now is the bottom graph (Chart5). If anyone is interested in seeing the code, I have put up a pastebin sample.
PasteBin Sample Code
And a TeeCharts.tar.gz is accessible to anyone who wishes to see a sample of the code, as well as the data sample.
filetolink.com Source Files
I no longer feel the need for mathematical equation to differentiate the top graphs from the bottom (because the bottom axes are automatic where as the top are defined). I intend to only use the space which is adherent to the visible space, and do not intend to extend in either direction (left or right). That means at this point the size of the graph does not matter, because once I over populate the charts above, the position in the bottom graph would become irrelevant, and therefor I do not intend to use the bottom chart.
The next step is to save the positions of the boxes so that they can reappear when the graph is shift from left (past data) to the right (live data). And then uses the buttons above to make the appropriate action to the graphs.
I would like to know what way would be the most sufficient way to record the positions of the rectangles, so when the chart is shifted (via the ScrollBar1), the rectangles are moving with the direction of the scrollbar. But I'm sure I can achieve that.
I think I have found a solution. The red squares are only prevalent for the visual aspect, they can be drawn on, I don't need to do anything special with each chart, as I already know what the X0..Y1 parameters are, they are known from the initial chart. The problem h/e has to do with the initial chart. As long as the screens are all full, I can zoom in correctly w/ alignment with on all the charts (ZoomRect/Rectf(X0..Y1))
But what kind of equation would it take to adjust the charts that are not in the same zoom / max / min when the Chart5.Axes.Bottom.Automatic = True?
From there I just simply have to disable the immediate zoom feature, and allow buttons to become functional, to decide what the next course of action would be.
I am using openlayers-3 modify interaction to edit vector layers. When a polygon/polyline is being edited, if mouse is close to a line segment, a small circle is drawn and dragging it creates a new vertex or moves an existing vertex, depending on where on the segment I was hovering.
Now, sometimes this is very difficult to understand if I am hovering on an existing vertex, or on middle of a segment. I have thought about two solutions to the problem:
Highlight the segment I am hovering with a different style so that I
can see its edges.
When hovering on an vertex, style the small
circle with a different style.
Is there a way to achieve any of the two?
It can be done changing the interaction condition like:
var selectPointerMove_Highlight = new ol.interaction.Select({
condition: ol.events.condition.pointerMove
});
map.addInteraction(selectPointerMove_Highlight);
I have an online example.
An instance of TChart in Delphi does a nice job of making a graph showing points. This is the "Point" series in the TeeChart gallery.
I would like to draw lines between some, but not all, of the points.
For example, image a scatter diagram of points, which is easy to make with Delphi/TChart. My objective is to draw straight lines between some of the points.
Is this possible?
This code works:
With Chart2.ChartRect do
begin
Canvas.MoveTo(0,0);
Canvas.LineTo(500,500);
end;
The line crosses over the graph, except the line is not visible over the graph. It seems as if the graph much have its own canvas but I can't find any documentation about finding and using it.
So, I need to find the coordinates of some points, as created by TChart, then draw a line between them.
Some options:
As David Heffernan said, the best option may be to use a series that supports both line segments and pointers. TLineSeries seems to be the perfect series to do this.
The problem here is that this series draws a line segment between each two consecutive points. You can make a point to be null with setNull(index) method and this will make the pointer at that index to disappear, but the predecessor and successor line segments will disappear with it.
The easiest solution could be creating a TMyLineSeries inheriting from TLineSeries to override DrawValue method as explained here.
Add a null point after each point you want to be visible. In this option, the only points not followed by a null point would be those where you want a line segment to be drawn.
Add a TLineSeries per line segment to be drawn.
You always have the possibility to use custom drawing techniques as LU RD said.
Attempting to paint lines yourself is not the way to proceed. The design basis of charting controls is that you define the chart in logical terms and let the control deal with painting it.
So, the way to proceed is to add some line series that represent the lines you wish to be drawn. You can perfectly well add these line series in addition to the other series of your chart.
Regarding your code that attempts to paint on the chart canvas, you should be aware that painting is a delicate process. The design of the system is such that control surfaces are not persistent. Controls are painted in response to the WM_PAINT message. So, whilst you may be able to paint on a control's canvas as you please, what you paint will survive only until the next cycle. Once the control becomes invalid, it needs to repaint itself. The lesson here is, as a general rule, only to paint in response to WM_PAINT messages. Or, in OnPaint events or overridden Paint methods which are called by the VCL in response to WM_PAINT.
To interconnect some points you must follow the drawing principle, all drawing must be done in a paint event.
In TChart, best option here is to do custom drawing in the OnAfterDraw event.
procedure TForm1.Chart2AfterDraw(Sender: TObject);
begin
With Chart2.ChartRect do
begin
Canvas.MoveTo(0,0);
Canvas.LineTo(500,500);
end;
end;
If you need to know the canvas coordinates for a given point in your array of points.
MyYPosX := Series1.CalcXPos( Series1.XValue[ 0 ] ); { <-- first point }
MyYPosY := Series1.CalcYPos( Series1.YValue[ 0 ] ); { <-- first point }
There is a chapter in the TChart help that is a good introduction to custom drawing: "Custom drawing on the Chart".
From the help:
When to draw ?
The order in which you draw to the Canvas is important.
If you wish Custom drawn items to appear above Chart Series you should use the Chart OnAfterDraw event. The Chart1.OnAfterDraw event is fired each time the Chart component is redrawn, just before copying the internal bitmap to screen.
You can place Custom drawn items above the Chart grid and below the Chart Series by placing your code in the Chart OnBeforeDrawSeries event.
Key Chart Paint events:
OnBeforeDrawChart
OnBeforeDrawAxes
OnBeforeDrawSeries
OnAfterDraw
Having a ChartSeries, I would like display a certain text on a label moving the mouse above the ChartValues. But only the line is active for me and not the EndPoint (definitely the Value…)
I would like if the EndPoint (a Circle, actually) would be active instead of the line and moving the mouse above this circle, my text can be appeared. Thanks.
You could try the MarkTips tool.
If you have a TLineSeries with Pointer.Visible=true, the mark tips tool will appear when you have the mouse over the line and over the pointer. If you only want it when you have the mouse over the series pointer, you could have a TLineSeries with Pointer.Visible=false and also a TPointSeries with the same data, and the MarkTips tool assigned to the TPointSeries.
Please have a look at this screenshot
alt text http://www.maclife.com/files/u18/Yep3-big.jpg
I think these are the main features of such a 'tag panel':
1) Each tag on the panel is a standalone control and can be clicked
2) Auto line wrapping when there is not enough space to show the next tag in the current line.
3) Rounded corner rectangle border for each tag is a nice-to-have feature.
I want to implement the similar function in Delphi, Is there an existing control to do this? If not, what's the best way to implement such a control?
Thank you.
When you are on a recent Delphi version use a TFlowPanel and some appropriate controls for the tags. A simple TButton or a TLinkLabel should do for that.
Each clickable tag doesn't necessarily have to be its own control. It just has to be a region that you can detect being clicked.
Suppose you represent each area as a Windows region. You can figure out how wide each one should be based on its text with the TCanvas.TextExtent function. Then create a region with a function like CreateRectRgn. For rounded corners, try CreateRoundRectRgn instead. You can test for mouse events in each region with the PtInRegion function. You can paint borders around them with FrameRgn. The last obstacle is to draw them on the screen so they'll all fit. You're creating the regions and you know their widths, so assign tags to a row until you run out of space, and then start the next line.
There are two possible solutions to custom alignment in Delphi 7. You can make your own flowpanel by deriving from TCustomPanel and override the AlignControls( )-method, or you can set alignment to alCustom and handle the OnAlignPosition-event.
I guess I would have gone for the TCustomPanel-derivative option. TFlowPanel in form Delphi 2007 uses that option- I have to admit, though, that I have never tried either my self...