Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "QMLMakie"
uuid = "08f9cac3-3b11-4f1c-9d88-d0e81c500f64"
version = "0.3.0"
version = "0.3.1"
authors = ["Steffen Haug <stehau@pm.me>", "Bart Janssens <bart@bartjanssens.org>"]

[deps]
Expand All @@ -11,11 +11,11 @@ Observables = "510215fc-4207-5dde-b226-833fc4488ee2"
QML = "2db162a6-7e43-52c3-8d84-290c1c42d82a"

[compat]
CxxWrap = "0.17.3"
CxxWrap = "0.17"
GLMakie = "0.13"
ModernGL = "1"
Observables = "0.5"
QML = "0.11"
QML = "0.12"
julia = "1.10"

[extras]
Expand Down
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,22 @@ It allows embedding hardware-accelerated interactive plots in Qt applications.

## Quickstart

The following example simply shows the first [lineplot example](https://docs.makie.org/stable/tutorials/getting-started) from the Makie documentation in a QML window. It uses the `MakieViewport` QML component that is provided by QML.jl, and then sets the `scene` property of that component to the Makie figure, by passing it to a QML context property named `plot`.
The following example simply shows the first [lineplot example](https://docs.makie.org/stable/tutorials/getting-started) from the Makie documentation in a QML window. It uses the `MakieArea` QML component that is provided by QMLMakie.jl (obtained using `import Makie` in QML), and then sets the `scene` property of that component to the Makie figure, by passing it to a QML context property named `plot`. The `MakieArea` component is an extension of the `MakieViewport` from QML.jl, adding handling of the events so e.g. mouse controls work.

```julia
ENV["QSG_RENDER_LOOP"] = "basic"

using GLMakie
using QMLMakie
using QML
QML.setGraphicsApi(QML.OpenGL)

# Data
seconds = 0:0.1:2
measurements = [8.2, 8.4, 6.3, 9.5, 9.1, 10.5, 8.6, 8.2, 10.5, 8.5, 7.2,
8.8, 9.7, 10.8, 12.5, 11.6, 12.1, 12.1, 15.1, 14.7, 13.1]

# Makie plotting commands
f = Figure()
ax = Axis(f[1, 1],
fig = Figure()
ax = Axis(fig[1, 1],
title = "Experimental data and exponential fit",
xlabel = "Time (seconds)",
ylabel = "Value",
Expand All @@ -35,24 +34,24 @@ mktemp() do qmlfile,_
qml = """
import QtQuick
import QtQuick.Controls
import jlqml
import QtQuick.Layouts
import Makie

ApplicationWindow {
title: "Makie plot"
visible: true
width: 640
height: 480

MakieViewport {
MakieArea {
anchors.fill: parent
scene: plot
}

}
"""

write(qmlfile, qml)
loadqml(qmlfile; plot = f)
loadqml(qmlfile; plot = fig)
exec()
end

Expand Down
2 changes: 0 additions & 2 deletions examples/Lorenz/lorenz.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
ENV["QSG_RENDER_LOOP"] = "basic"

using GLMakie
set_theme!(theme_black())

Expand Down
2 changes: 0 additions & 2 deletions examples/lineplot.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Example based on the first Makie tutorial at:
# https://docs.makie.org/stable/tutorials/getting-started

ENV["QSG_RENDER_LOOP"] = "basic"

using GLMakie
using QMLMakie
using QML
Expand Down
37 changes: 17 additions & 20 deletions src/QMLMakie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ qmlwindow(screen::GLMakie.Screen{QMLWindow}) = screen.glscreen
function setup_screen(screen::GLMakie.Screen, fbo)
win = qmlwindow(screen)
win.context.fbo = fbo
screen.postprocessors[end] = GLMakie.to_screen_postprocessor(screen.framebuffer, screen.shader_cache, QML.handle(fbo))
win.fbo_size = sizetuple(fbo)
win.window_area[] = Rect2i(0,0,round.(win.fbo_size ./ QML.effectiveDevicePixelRatio(win.quickwin[]))...)
return screen
Expand Down Expand Up @@ -87,32 +88,24 @@ end

function Makie.disconnect_screen(scene::Scene, screen::GLMakie.Screen{QMLWindow})
qmlwin = qmlwindow(screen)
sleep(0.3) # wait for delayed actions such as zoom or pan
Observables.clear(qmlwin.window_area)
disconnect!(screen, Makie.frame_tick)
return
end

function GLMakie.pollevents(screen::GLMakie.Screen{QMLWindow}, frame_state::Makie.TickState)
GLMakie.gl_switch_context!(screen.glscreen)
screen.render_tick[] = frame_state
return
end

function Base.display(screen::GLMakie.Screen{QMLWindow}, scene::Scene)
invoke(Base.display, Tuple{GLMakie.Screen,Scene}, screen, scene)
GLMakie.pollevents(screen, Makie.RegularRenderTick)
GLMakie.poll_updates(screen)
GLMakie.render_frame(screen)

win = qmlwindow(screen)

# Up to a potential rounding error, both of these should be the same
wmakie,hmakie = screen.framebuffer.resolution[]
wqml, hqml = win.fbo_size

# Bind the QML FBO for drawing
QML.bind(win.context.fbo)
# Bind FBO 0 (used by GLMakie by default) as source
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)
# Copy the GLMakie color buffer to QML
glBlitFramebuffer(0, 0, wmakie, hmakie,
0, 0, wqml, hqml,
GL_COLOR_BUFFER_BIT, GL_LINEAR)

return
end

Expand All @@ -121,12 +114,16 @@ function on_context_destroy(screen)
end

function renderfunction(screen::GLMakie.Screen{QMLWindow}, sceneorfigure)
scene = Makie.get_scene(sceneorfigure)
if !Makie.is_displayed(screen, scene)
# This makes sure the axis is autoscaled as it is in the regular Makie
Makie.update_state_before_display!(sceneorfigure)
try
scene = Makie.get_scene(sceneorfigure)
if !Makie.is_displayed(screen, scene)
# This makes sure the axis is autoscaled as it is in the regular Makie
Makie.update_state_before_display!(sceneorfigure)
end
display(screen, scene)
catch
Core.println("exception in render")
end
display(screen, scene)
# Since the cfunction call specifies void, it is important that the renderfunction doesn't return anything.
return
end
Expand Down
Loading