Skip to content

Introduce Qt6-based implementation for TCanvasImp - #22736

Merged
linev merged 30 commits into
root-project:masterfrom
linev:qt6_canvas
Sep 21, 2026
Merged

linev merged 30 commits into
root-project:masterfrom
linev:qt6_canvas

Conversation

@linev

@linev linev commented Jul 1, 2026 •

Copy link
Copy Markdown
Member

After setting Gui.Factory: qt6 TQt6Canvas canvas implementation will be created in ROOT.

Painting with TQt6PadPainter redirected to QPainter class where all ROOT primitives -
polyline, fillarea, polymarkers, line, box, text - are implemented.
Mouse click/move/release/wheel/enter/leave events are processed.
Menu implemented with QMenuBar, toolbar with QToolBar, status line with QStatusBar.

Also context menu is implemented providing TQt6ContextMenuImp class.
It includes special dialog for input of method parameters.
Also toggle menu item with checked states should work.

Simple dialogs for line, fill, text and marker attributes are implemented.
For now they invoked when correspondent context menu command is activated,
later one can provide better integration via gui factory.

Provided implementation fully avoids gVirtualX usage - pure Qt graphics is used.
TQt6Canvas works now with basic primitives like TLatex, TLine, TBox
and with TH1/TH2 classes in 2D and 3D plots.
Some ROOT classes may crash while they internally use gVirtualX for event handling.
These classes will be fixed/improved later.

Classes declared in ROOT::Experimental namespace. I re-wrote commits history (took 1.5 hours) to have classes defined from the beginning as experimental. These are:

  • ROOT::Experimental::TQt6Canvas
  • ROOT::Experimental::TQt6PadPainter
  • ROOT::Experimental::TQt6GuiFactory
  • ROOT::Experimental::TQt6Application

There are know problems/issues/open questions:

  • running of Qt and ROOT event loop together. Now ROOT TApplication invokes qt events per timer, but one can have opposite situation when ROOT classes used from QApplication. At least our API should be capable to handle both situations.
  • one has to prevent gVirtualX/gClient initialization completely, now only gClient is skipped
  • no browser, no fitpanel, no treeviewer; TGuiFactory can create them, but do we want to implement them for alternative graphics backends; do we want to reuse TRootBrowser or RBrowser code?
  • probably we need switch for root executable like root --backend=qt6; there are more backends expected
  • text allign is not identical (one or two pixels difference) with gVirtualX implementation, need to be investigated
  • not all canvas menu commands are provided, probably one can move some functionality to base classes;
  • no public API yet to reuse canvas in external Qt6-based projects, to be defined in the future

This is first (but not the only) new graphical backend which can fully replace gVirtualX-based implementation.
After finalizing of API some other - more simpler (like raylib) or more advanced (like Vulkan) - can be exercised.

@linev linev self-assigned this Jul 1, 2026
@linev
linev requested a review from bellenot as a code owner July 1, 2026 10:41
@linev
linev requested review from dpiparo and pcanal as code owners July 1, 2026 10:41
@linev linev added in:Graphics skip ci Skip the full builds on the actions runners labels Jul 1, 2026
@linev
linev marked this pull request as draft July 1, 2026 10:41
@silverweed
silverweed self-requested a review July 8, 2026 07:12
@linev
linev force-pushed the qt6_canvas branch 5 times, most recently from 5f7c92a to bf253b8 Compare July 29, 2026 08:04
@linev linev changed the title [EXPERIMENTAL] Introduce Qt6-based implementation for TCanvasImp [skip-ci] Introduce Qt6-based implementation for TCanvasImp Jul 29, 2026
@linev linev removed the skip ci Skip the full builds on the actions runners label Jul 29, 2026
@linev
linev marked this pull request as ready for review July 29, 2026 08:34
@linev
linev requested a review from couet July 29, 2026 08:35
@linev linev closed this Jul 29, 2026
@linev linev reopened this Jul 29, 2026

@silverweed silverweed left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started reviewing this PR and made it about 10 commits in, but it seems to me that this is still in a state not ready for review: there are several commits where something is introduced and later changed in other commits, as well as many leftovers of commented-out code and debug prints.

Please try reorganizing the commits in a more review-friendly manner to help understanding what is going on (and also to not leave many commits with an incomplete state in the history when this is merged)

Comment thread gui/qt6canvas/inc/TQt6Canvas.h Outdated
Comment thread gui/qt6canvas/src/TQt6Canvas.cxx
Comment thread gui/qt6canvas/src/TQt6Canvas.cxx
Comment thread gui/qt6canvas/src/TQt6Canvas.cxx Outdated
Comment thread gui/qt6canvas/src/TQt6Canvas.cxx Outdated
Comment thread gui/qt6canvas/src/QPaintWidget.cpp Outdated
Comment thread gui/qt6canvas/src/QPaintWidget.cpp Outdated
Comment thread gui/qt6canvas/src/QPaintWidget.cpp
Comment thread gui/qt6canvas/src/QPaintWidget.h Outdated
Comment thread gui/qt6canvas/inc/TQt6PadPainter.h
@linev

linev commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

@silverweed

I know that commits are not looking perfect - but they show the way how I develop the code.
They always compiled and in most cases functional to some extend.

I use a lot code from our go4 project where QtRoot canvas with TVirtaulX-based graphics is used. Whats why in original commits code appears which than removed or significantly changed.

Such big development will never be linear and clear.
My aim - not sorting commits nicely but produce finally code which works.
Internal API will be changed many times anyway.
Most probably class names will be changed.
Even original folder name qt6canvas will be changed - while already now it is more than TQt6Canvas.

But this is the way how software is developed.
Otherwise ROOT repository will consists not from 90K commits but from 100 - by number of our releases.

@silverweed

Copy link
Copy Markdown
Contributor

But this is the way how software is developed.
Otherwise ROOT repository will consists not from 90K commits but from 100 - by number of our releases.

This is such a mischaracterization of what I asked that I don't know what to say about it. Just, that PRs and commits in a team project should not look as they would if you were developing the software by yourself, otherwise whoever reviews this code will have a much harder time understanding it properly, which is the point of reviewing it in the first place.

@linev

linev commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

My point is - rewriting/reorganizing commits now makes no sense.

There are fundamental problems which should be resolved and discussed:

  • way how invocation of TCanvas::Update() match to Qt logic; is same will work with absolutely different GUI libs
  • handling of mouse/keyboard events; nicely works with Qt, can be a mess in other cases
  • running several canvases with their menus/dialogs in parallel (now it is not yet possible),
  • coexistence of QApplication and TApplication with their events loops (works in go4, but in opposite way as it runs in this prototype)
  • running ROOT graphics/gpad classes without loading X11/Cocoa/TWin32gdk libraries and when gVirtualX and gClient are nullptr.

All kind of debug output, commented out code, unused variables, compiler warnings can be resolved once such crucial points are proved to be working.

@github-actions

github-actions Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

Test Results

    23 files      23 suites   3d 13h 48m 32s ⏱️
 3 853 tests  3 853 ✅ 0 💤 0 ❌
78 505 runs  78 505 ✅ 0 💤 0 ❌

Results for commit 7037a68.

♻️ This comment has been updated with latest results.

linev added 21 commits August 17, 2026 14:56
Support special fill patterns 3000..3025 reusing X11 pixmaps
Implement box and fillarea painting
Once generic API exists to paint markers -
use it here instead. There are 5 different places
in ROOT which repeats again and again all markers implementation
It is not equivalent with TTF font and must be about 0.75
Use QString::toLatin1() method, otherwise special characters
like used in symbols.ttf, are handled as utf-8 as displayed wrongly
Like press, move, release mouse button.
On the right mouse button actiate context menu.
For methods with arguments provide special dialog.

Code partially copied from Go4 project
and originally was developed in 2002
by Denis Bertini and improved later by Sergey Linev
It fully dismiss standard GUI classes and
only allows to create Qt6canvas.
Aim to provide specialized implementation for
application and context menu

Declare it in ROOT::Experimental namespace
It is implementation for context menu used inside qt6_canvas
Idea to let handle right mouse button click in the
canvas handler which will invoke implementation class
This is default place where all normal or custom items
for the class are collected. By large copy code from
TRootContextMenu.
Reuse several methods from TContextMenu to
create labels for arguments and afterwards
execute selected method with provided list of arguments.
These are:
* open ROOT file,
* Save as dialog
* Menu items with supported formats

Use QFileDialog, list of supported extensions can be moved later to base class
Implement toggling of empty QToolBar
Implement toggling of status branch
Implement tooltip event handling and toggling of such mode
For line, fill, text, marker attributes provide
dialogs to avoid ROOT crash while default editors does not work in Qt

For all attributes reuse colors editors with opacity
Required for zooming and corrects interactivity handling in ROOT
Add \class mark for all used classes
Provide some remarks around QPainter and paintEvent handler
Remove several debugging printf
Make headers #ifdef with same syntax
Idea to move dedicated application initialization there
When TQt6Application is created immediately create also QApplication.
In the future one can make it optional
Gives information to application that virtualx is not required.
Use new TAttMarker::GetMarkerShape() method
Prevent access to nullptr
Prevent out-of-bound access to markers
Remove timeout from mouse handling

AI-assist with qwen llmbot
@couet
couet removed their request for review September 1, 2026 09:02

@jblomer jblomer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle looks good to me! I went commit by commit, some comments are invalidated by later commits, feel free to ignore them.

Are the Q... classes visible as symbols? If so, I think they should go in ROOT::Internal (can be another PR).

Comment thread gui/qt6canvas/inc/LinkDef.h
Comment thread gui/qt6canvas/inc/TQt6Canvas.h Outdated
Comment thread gui/qt6canvas/src/TQt6Canvas.cxx
Comment thread gui/qt6canvas/src/TQt6Canvas.cxx Outdated
Comment thread gui/qt6canvas/CMakeLists.txt Outdated
Comment thread gui/qt6canvas/inc/TQt6PadPainter.h
Comment thread gui/qt6canvas/src/TQt6Canvas.cxx Outdated
Comment thread gui/qt6canvas/inc/TQt6PadPainter.h
Comment thread gui/qt6canvas/src/TQt6PadPainter.cxx
Comment thread gui/qt6canvas/src/QRootMethodDialog.cpp Outdated
@linev

linev commented Sep 21, 2026

Copy link
Copy Markdown
Member Author

@jblomer

I will merge PR and will try to create next one with my newer changes - TTF implementation and basic graphics editors.

@linev
linev requested a review from silverweed September 21, 2026 07:32
@linev
linev dismissed silverweed’s stale review September 21, 2026 07:38

Many comments are valuable, but can be considered when final implementation will be done. Currently code changes rapidly, methods appears and then removed again. At its final stage TQt6PadPainter will be much more compact and lines which are discussed now simply disappear. Same with TQt6Canvas - lot of gVirtualX-related methods will be gone. Therefore I see no needs to already now make each commit and each comment perfect.

@linev
linev merged commit bc9232d into root-project:master Sep 21, 2026
29 of 33 checks passed
@linev
linev deleted the qt6_canvas branch September 21, 2026 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants