Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: initial stab at an abstract graphics/GUI interface #3981

Closed
wants to merge 1 commit into from

Conversation

timholy
Copy link
Member

@timholy timholy commented Aug 7, 2013

Here's a beginning at a generic specification of a window-management/GUI interface. It is toolkit-agnostic (and consequently can't do very much), but it already attempts to provide some facilities that we currently lack. I'm posting it at this early phase because there's enough in place to be able to ask whether this is moving in the right direction, and it's a lot of work to go much further than this.

Most importantly, this organizes graphics objects into a tree, making it possible to query the list of windows, delete objects, etc. For example, currently we have no way (that I know of) of closing all opened windows in a session, short of quitting the session; this will fix that, among other things. In theory you should be able to use multiple toolkits simultaneously (e.g., Tk and Gtk) and everything will work automagically (whether that's wise is another matter...).

For Tk, something like this pull request this will allow us to resolve a currently-messy issue: the split between TkWidget and Tk_Widget etc (the various container types). We have two ways of creating windows, one of which can store elementary parent/child relationships and the other which cannot. Moreover, even if you create objects with the Tk_Widget type, traversing towards the root returns a TkWidget, which means that you've lost the type information (including information about the children in container-objects). Consequently, if you go up a level, you can't go back down again. Fixing such issues should, among other things, make it much easier to address JuliaGraphics/Tk.jl#53.

I've gone to some effort to insulate the "toolkit implementer" from the details of tree traversal (and particularly, from having to maintain the organization of the tree). The basic design principle is that GraphicsHandles are to be returned by all operations that create graphics objects, and these handles are simply nodes in a tree. However, they are typed nodes, and consequently when used as arguments they will dispatch to the right functions.

None of this is "wired in" yet; you have to include()/using (which facilitates testing at this early stage). Here's a demo session:

julia> include("trees.jl")

julia> include("GUI.jl")

julia> include("/tmp/guitest.jl")

julia> using GUI, GUItest

julia> win = window("test window", 400, 200)
Window node:
  parent: root node
  children: <none>
  data: Window("test window",400,200)

julia> b = button(win, "Done", x->x)  # deliberate mistake, we want buttons in frames
ERROR: no method button(AryNode{Window},ASCIIString,Function)

julia> f = frame(win)
Placing at position 1, 1
Frame node:
  parent: Window node
  children: <none>
  data: Frame(RGB(0.85,0.85,0.85))

julia> b = button(f, "Done", x->x)
Placing at position 1, 1
Button node:
  parent: Frame node
  children: <none>
  data: Button("Done",# function)

julia> win
Window node:
  parent: root node
  children: Frame
  data: Window("test window",400,200)

julia> f
Frame node:
  parent: Window node
  children: Button
  data: Frame(RGB(0.85,0.85,0.85))

And here was my guitest.jl, which is basically what the "toolkit implementer" needs to write:

module GUItest

using Trees
using GUI
using Color

export # types
    Button,
    Frame,
    Window,
    # functions
    grid

type Window <: AbstractWindow
    title::String
    w::Int
    h::Int
end

width(win::Window) = win.w
height(win::Window) = win.h

type Frame <: AbstractFrame
    color::ColorValue
end
Frame(rgb::(Real,Real,Real)) = Frame(RGB(rgb[1],rgb[2],rgb[3]))

type Button <: AbstractButton
    msg::String
    callback::Function
end

grid(obj, col, row, justify) = println("Placing at position ", col, ", ", row)

end

You can see the generic wrapper releases the implementer from having to worry about any of the tree-hierarchy details.

@timholy
Copy link
Member Author

timholy commented Aug 7, 2013

In addition to the usual suspects when it comes to graphics, @stevengj it may be worth looking into how this might interact with your Display plans.

@StefanKarpinski
Copy link
Member

I have very limited qualifications to comment here, but this seems like a great direction to me. Being able to abstract out this common language for doing GUI stuff is a big deal.

@timholy
Copy link
Member Author

timholy commented Aug 7, 2013

I should also add that despite the pull request against master, I'm well aware that this may be 0.3 material.

@JeffBezanson
Copy link
Member

I also generally like this direction. The biggest problem is that it seems not much can really be done abstractly. For example there is no need for a window function that requires Window; you might as well just use Window directly if it is available.

A slightly different possible direction is to define a full object model, where you might write (in a mathematica-ish way):

Window("test", w, h, Frame(Button("OK", x->x), Button("Cancel", x->x), fill=true))

This would then be passed to display for rendering by whatever system is available. Basically imposing the same structure as AryNode but with more semantic info. Either that or just have a "reference implementation" of this high-level GUI API using Tk or Gtk, and other backends can implement the same API if they want.

@stevengj
Copy link
Member

stevengj commented Aug 7, 2013

There are zillion abstract GUI toolkits out there. Can you make a convincing case that your proposal adopts best practices? How does what you are doing relate to:

Let's not re-invent the wheel here.

@timholy
Copy link
Member Author

timholy commented Aug 7, 2013

there is no need for a window function that requires Window; you might as well just use Window directly if it is available

The only thing window really does is wrap the output of Window in a GraphicsHandle. It's a detail that the toolkit implementer would otherwise have to remember, but it's probably not a big deal. Perhaps the best bet would be to come up with a shorter name than graphicsobject() and hope that the toolkit wrappers make use of it. That may be more realistic anyway, because I suspect that the availability of more specialized widgets will vary.

@stevengj
Copy link
Member

stevengj commented Aug 7, 2013

Why should we have a toolkit-agnostic approach rather than just picking one good one, like Qt or wx? It's a huge PITA to deal with things like matplotlib that support 15 different toolkit backends, each with slightly different semantics.

@timholy
Copy link
Member Author

timholy commented Aug 7, 2013

There are zillion abstract GUI toolkits out there. Can you make a convincing case that this adopts best practices?

This is not an attempt to replace Qt. Looking back, I see the title for this PR may be a little confusing on that score :-).

This is an attempt to bring some small measure of consistency and rationality to our current mess of return types from functions that create new graphics objects. Pretty limited scope, really, but it's currently a blocking issue for making progress in graphics.

@stevengj
Copy link
Member

stevengj commented Aug 7, 2013

Once you start adding buttons and other widgets, it seems like it will quickly get out of control and become another AWT. Even if that ends up being what we want, we should do it intentionally from the beginning and look carefully at other implementations in high-level languages.

@JeffBezanson
Copy link
Member

Basically we have the same "immediate mode" vs. "deferred mode" decision here as in Graphics. For graphics you can have an object model (like Winston) including Line, Polygon, etc. objects, and also functions like line_to for immediate drawing.

For plain drawing, immediate mode is preferred since a vector graphic is not really stateful, and one tends not to need a hierarchy of lines and such (though you might have a hierarchy of canvases). We could write code to render from a vector object model to an immediate mode API very straightforwardly, (e.g. draw(gc, l::Line) = (move_to(gc, ...); line_to(gc, ...))).

But GUIs might be different; all the APIs work by creating stateful objects, so maybe we should pick the object-model approach for GUIs by default.

@timholy
Copy link
Member Author

timholy commented Aug 7, 2013

Why should we have a toolkit-agnostic approach rather than just picking one good one, like Qt or wx? It's a huge PITA to deal with things like matplotlib that support 15 different toolkit backends, each with slightly different semantics.

Lots of prior debate here. I should have referenced JuliaGraphics/Tk.jl#35 in this PR. That issue also refers to an old malinglist discussion.

Bottom line, I'd also appreciate it if we pick just one and make it awesome. Even if we do that, however, I think something like this PR is necessary. It's basically part of a good wrapper even if we just have one toolkit. And currently, we have a fairly-mature-but-needs-cleaning-up wrapper around Tk, and a nice-start-but-not-fleshed-out wrapper around Gtk.

@timholy
Copy link
Member Author

timholy commented Aug 7, 2013

But GUIs might be different; all the APIs work by creating stateful objects, so maybe we should pick the object-model approach for GUIs by default.

Yes, I think with GUIs (and even just figure window management) it's all about managing state. Some of that can be generic, and I think this PR (because it's quite minimalistic) largely fits within the subset of functions that we can reasonably hope is amenable to a generic/portable solution.

Whether we can go a great deal further than this in a generic wrapper is less clear. Whatever we write, it should be a facilitator, not a prison.

@JeffBezanson
Copy link
Member

The goal of this is to provide an easy way to make one-off exploratory GUIs. Something like EasyGUI is a good model. Most existing toolkits like Tk and Gtk are either too hard to use and/or don't match Julia well. I don't really want to support multiple backends either; I'd be fine with one that works reasonably well everywhere.

I'm not totally convinced we need anything in Base for this. My current plan was to move the simple abstractions like Window and Button from the Tk package into their own package, and then you can pick whether to use full Tk, or the "EasyGUI" equivalent. Personally I only want the latter.

@stevengj
Copy link
Member

stevengj commented Aug 7, 2013

You wouldn't design a programming language without looking closely at other languages first and making explicit choices. GUI toolkits, simple or complex, have a history of so many failures and so much complexity creeping into even "simple" stuff (think of AWT on both counts) that I think you'd be crazy not to do a survey first and explicitly fashion your design after successful models, or at least explain what techniques you are adopting and which you are rejecting.

Let's please avoid half-assed toolkit design in a vacuum, with the excuse that we're only handling simple cases so we don't need to think much about where this is going.

@timholy
Copy link
Member Author

timholy commented Aug 7, 2013

I'm not totally convinced we need anything in Base for this. My current plan was to move the simple abstractions like Window and Button from the Tk package into their own package

Another view of this PR is to say simply: to support graphics, Base needs an implementation of a tree data structure. Providing that---and nothing more---is more than half of the code in this PR, and pretty close to the only real "work" being done. A detail is that it has to be one that allows the different nodes to have different types so we can do dispatch on different types of graphics objects. (EDIT: and for dispatch you need to expose that type as a parameter of the node.)

I think the issue being addressed here is less "what is a Button and how can we make it simple to use?" and more "how do you keep track of the zillions of items that get created as you build a GUI"? That is, without having to write functions like

display(inputs...)
    # lots of code here
    return windowhandle, canvashandle, donebuttonhandle, cancelbuttonhandle, framenumberslider, ...
end

ImageView and Winston both create their own custom compound objects to package up things that might be of interest to the calling function, but the choice between being comprehensive in your return type and keeping things reasonably simple means that some things---especially in a GUI like ImageView---are just "lost" (they can be updated by a callback created within ImageView.display but are otherwise opaque to any other piece of code). With graphics objects packaged up in a tree---and support for trees in Base---none of this would be an issue because it's packaged in a consistent format amenable to inspection.

In other words, basically we have a big hole in our data structures support. It's just happens that graphics is the place that most pressingly needs this support. (Note that I also wrote a left-child-right-sibling tree for parsing the callgraph in ProfileView, so that's two trees I've had to write in a week and a half!)

@stevengj
Copy link
Member

stevengj commented Aug 7, 2013

What data structures and access models for widgets do successful toolkits use?

Moreover, once you have a tree of widgets where you can access callbacks and other properties of the widgets, you are basically designing an AWT. And if you can't access those properties, then the tree is useless. So, you haven't really answered my objection.

@timholy
Copy link
Member Author

timholy commented Aug 7, 2013

Don't know whether Matlab counts, but there every graphics handle lets you query parents and children.

Qt: C++'s inheritance mechanism contributes strongly to a tree structure. More directly, all graphics objects inherit from QWidget, which inherits from QObject, which has an interface that implements tree-navigation.

So for both of these, trees are basically the "root" (pun intended) of the graphics system. We don't have a tree in base, and we need one :-).

@JeffBezanson
Copy link
Member

We are making explicit choices. Some of the choices are being discussed here, and some are being or have been discussed elsewhere. Tim and I (and other Julians) have used many gui toolkits. I don't think anybody is advocating that we be half-assed and not think. I do advocate a pretty extreme level of API simplicity though. I'm not worried about being trapped by this, since more widgets can be added, and more options can be added without breaking code (e.g. with keyword args).

Most GUI toolkits are very tied to their implementation language. In C++ you often see getFirstChild() and getNextSibling() methods.
I'm not sure I want a tree type distinct from widgets themselves. For one thing it doubles the number of objects.

@stevengj
Copy link
Member

stevengj commented Aug 7, 2013

It would be more satisfying (and convincing) to see a rationale along the line of "Qt has a tree consisting of these kinds of objects with this kind of interface" (not to mention their whole signals and slots approach, whose analogue in Julia would probably be more like publish/subscribe coroutines than passing function pointers), SWT does X (e.g. in SWT the windows ["shells"] are not root nodes, and there is instead a top-level "display" which manages event loops, global menus?, etc.), and wx does Y. We are doing Z, because....

A lot of toolkits also have concepts like "Layouts" (e.g. in Qt) to automatically manage widget arrangements. And then there is the whole question of graphical GUI builders, which are important if you are going for maximum ease-of-use.

@timholy
Copy link
Member Author

timholy commented Aug 8, 2013

Moreover, once you have a tree of widgets where you can access callbacks and other properties of the widgets, you are basically designing an AWT.

It's called "multiple dispatch." In this PR, a node is this:

type AryNode{T} <: AbstractNode
    parent
    children::Set
    data::T
end

That's it. All the magic is in T.

And if you can't access those properties, then the tree is useless.

Not true. Do you realize that currently, while ImageView blows Matlab out of the water for many image-viewing tasks (and hence you might think we're really sophisticated), we don't even have an analogue of Matlab's close all? That's precisely the kind of hole that this PR is intended to fill.

@stevengj
Copy link
Member

stevengj commented Aug 8, 2013

@timholy, it's precisely the question of T that is at issue here, not the design of a trivial tree data structure. Some key questions are what the widget hierarchy looks like, how the widgets are addressed, what kind of functionality the widgets expose, how the widget layout is specified, whether you use callback functions or publish/subscribe model or ..., how/what events are described, and so on.

If you just want to standardize close all function, of course, then you don't need to talk about widgets, but as soon as you start talking about specific widget functionalities you are entering AWT territory.

@timholy
Copy link
Member Author

timholy commented Aug 8, 2013

You're dismissing the trivial things, but the trivial things are the only things I'm interested in. There are many places in our current graphics API where a few well-placed tweaks will make a considerable difference in the programmer experience, and also let us do things that currently we can't do. That's true no matter whether this is the only API we ever get, or whether we in due course migrate to something else. Often good design has some element of abstraction to it (your Display mimetype stuff being a good example).

I have little taste at the moment for biting off enormous projects on the scale of what AWT sounds like it must be. I think you're projecting your unhappy python experience into a place where it's not necessary. When we get an awesome wrapper around Qt, I'll be a happy guy and probably use little else. But Jeff's EasyGUI idea will still be valuable for those folks who just want to have a single graph with an entry box they can use to tweak a parameter.

@stevengj
Copy link
Member

stevengj commented Aug 8, 2013

I'm just worried that we will solve the trivial problems in a way that makes it more difficult later to solve the hard problems. And the bitter experience of Java AWT (not to mention the many, many other GUI toolkits in the dustbin of history) shows that it is really easy to get widget abstractions wrong (to the extent that they had to pitch the whole thing in the trash and start over).

If you just want to keep track of what windows are open and be able to close them, that may be reasonable. It's when we start building simplistic abstractions for the things inside the window, for buttons and mouse events, that I get worried.

@vtjnash
Copy link
Member

vtjnash commented Aug 8, 2013

I'm not sure this needs to be in base. There could be a GUI metapkg which Tk, Gtk, etc. depend upon. which provides a basic "gui" layer.

Interfaces in Julia typically should be about functions (and abstract types), not the types that implement them. For example, implementing a close all function would only require a few edits in the Gtk package as it stands now. Supporting AryNode would probably require having a duplicate object hierarchy to describe the Gtk layout.

A lot of toolkits also have concepts like "Layouts" (e.g. in Qt) to automatically manage widget arrangements. And then there is the whole question of graphical GUI builders, which are important if you are going for maximum ease-of-use.

I was going to point this out as well. What you and Tk call a Frame is very similar to what Gtk calls a Layout. However, it's not clear to that this tree adequately reflects the infrastructure necessary for Gtk. Toolkits like GTK don't necessarily have generic "children", since the concept of child and layout is tightly coupled. What they have is probably best described as a hierarchy of layouts ending in an object (which may itself have a hierarchy of layouts).

@JeffBezanson
Copy link
Member

I don't believe widget abstractions are all that hard. As far as I can tell, the problems with AWT/Swing are that they look ugly and not native, people aren't quite happy with the layout managers, and code is verbose (common in java). In a generally terser language with closures things are easier. We also have the ability to add arguments and keyword arguments to methods without breaking code.

@vtjnash makes a good point; I'm not sure we want a "shadow hierarchy" of objects. I also doubt we can do much generically with a widget tree or an AbstractButton. There are two cases: either we're writing our own GUI API, or we're wrapping an existing toolkit. In the first case we can do whatever we want, and in the second case it will be hard to make the existing toolkit comply with whatever is specified in a possible Base.GUI. It is unfortunately quite different from Base.Graphics, where it is safe to assume a generic svg-like rendering model.

It matters a lot to decide what use cases we care about. For example, do we want to be able to display a gui, possibly to a web browser, just like we can an image?

@timholy
Copy link
Member Author

timholy commented Aug 8, 2013

For example, do we want to be able to display a gui, possibly to a web browser, just like we can an image?

Definitely an interesting question, but not one I plan to tackle personally any time soon (I simply don't have the expertise). Don't let me stand in anyone else's way though :-). Given Gadfly's terrific recent progress in displaying to a web browser, that seems like a natural context for exploring such questions.

@vtjnash, very useful feedback. I think we're zeroing in on the notion that this should largely be a Tk-specific cleanup. While I have everyone's attention, there are a few specific points worth bringing up for discussion.

Important questions:

  • AryNode is simply an implementation of a tree type (it has nothing specifically to do with graphics). Base, or a GUI.jl package?
  • The name AryNode distinguishes itself from another likely tree implementation, BinaryNode, but it's a fairly geeky choice. Any other suggestions? (Of course, if this lives in GUI.jl rather than Base, then it can be named something like GraphicsHandle, the name I currently give to an AryNode{T<:GraphicsObject}.)

Less-important questions (either I think I already know the right answer, or it's a small detail we can easily change later):

  • There were two implementations of the tree that I considered: the one illustrated here (AryNode contains the item-specific types) and an alternative in which parent and children are fields in each item-specific type (and so there is no outer container). I don't see big advantages either way, but to me this approach seems nicer because one can insulate the constructors and destructors of the item-specific types from having to worry about maintaining the tree structure (as long as each constructor wraps its result before returning). It also makes the tree generic rather than graphics-specific (which matters only if we decide this can go in base).
  • For children, use a Set or a Vector? Set provides fast random access (e.g., fast deletion), but does not allow children to be ordered. If we provide handles for each specific drawing element in a canvas (which may not be necessary, the hierarchy might just stop at the canvas level) then we might regret not being able to specify the order of the children (e.g., the order in which they are drawn to a canvas).

@stevengj
Copy link
Member

stevengj commented Aug 8, 2013

@JeffBezanson, I think the difficulty is precisely the fact that people want their widgets to look native, i.e. to use the native toolkit in the back end, contrasted with the fact that it is hard to write an abstract GUI and have an "existing toolkit comply with whatever is specified".

@timholy
Copy link
Member Author

timholy commented Aug 13, 2013

I'm working on this in Tk.jl, so closing here.

@timholy timholy closed this Aug 13, 2013
@jverzani
Copy link
Member

@timholy @JeffBezanson

Despite some earlier comments by myself in this thread about the how this is a bad idea, I have written a package that abstracts out some of the easier parts of writing a GUI. The backend is implemented for both Tk and Qt. The package readme is at https://github.com/jverzani/JGUI.jl/blob/master/README.md . If this seems useful in any way, I can add it to METADATA.

@JeffBezanson
Copy link
Member

Looks great, I hope to have time to dig into it. I need to think about how to do a more efficient and more julian manipulate. We are increasingly seeing groups that need highly productive graphics and GUI APIs.

@stevengj
Copy link
Member

Note that the IPython community is working hard on GUI manipulation capabilities (focusing on JavaScript widgets in the browser, I think). See ipython/ipython#4195

@JeffBezanson
Copy link
Member

It will be great to have that stuff in IJulia. If we had it now we probably wouldn't be working on things like this, assuming the performance is ok.

@stevengj
Copy link
Member

Once it lands in IPython, it sounds like it should be straightforward to implement the spec in Julia and leverage the same Javascript widgets.

@timholy
Copy link
Member Author

timholy commented Oct 15, 2013

@jverzani, I haven't looked at the details, but the principle is great! Can I finally stop robotically adding
pack(f, expand=true, fill="both") all the time? :)

@timholy
Copy link
Member Author

timholy commented Oct 15, 2013

@stevengj, @JeffBezanson, I think expanded browser-based GUI capabilities would be awesome, but I really doubt it will replace the need for a full GUI system. Among other problems, the browser itself intercepts too many things. For example:

  • Browsers seem to put an upper limit on the amount you can zoom in (on my system, chrome cuts you off at 500%); this makes them almost useless for interactively inspecting really big datasets, where you might zoom in and out by a factor of 100 or more.
  • ImageView would suffer mightily without good wheelmouse support (e.g., Ctrl-Alt-Scroll lets you pan along the z-axis, Shift-Scroll pans left/right, etc) and keybindings (e.g., the left-arrow pans left).
  • As far as I can tell it's not even possible to create a popup/context menu to operate inside a browser interface, because the browser wants to have its own context menu. Again, this is a real-world concern with a GUI like ImageView, which already exploits popup menus to launch a brightness/contrast sub-GUI, and will more so in the future (e.g., for interactive control of scalebars, etc).

Sometimes you basically need to take full control of the GUI environment, and the browser will never let you do that. Of course it would be possible with something built from the ground up based on WebKit, but that's a different issue.

@jverzani
Copy link
Member

@timholy

Well, you might not like pack(f, expand=true, fill="both") but it is shorter than

f[:sizepolicy] = (:expand, :expand)
push!(f)

@timholy
Copy link
Member Author

timholy commented Oct 15, 2013

How about fill(win, frame)?

@stevengj
Copy link
Member

Julia programs certainly need the option of full GUI access, but the question is whether we should have an AWT in Base that sits on top of existing platform-independent toolkits like Qt or Tk, as opposed to just having people pick a toolkit and use it directly.

(The zooming question is a red herring, since zooming of plots should be handled by the backend/widget interaction, not by the browser.)

@timholy
Copy link
Member Author

timholy commented Oct 15, 2013

Oh, I agree we should just pick Qt and be done with it :).

@vtjnash
Copy link
Member

vtjnash commented Oct 15, 2013

@timholy All of those things have been possible in a browser for many years. You can directly manipulate images and sound in HTML5*. The only area the browser falls short of desktop GUI toolkits is with respect to access to the local file system.

Qt sounds good to me. But until Julia can bind to C++, I've been advancing the state of Gtk: https://github.com/JuliaLang/Gtk.jl/tree/jn/layouts. I've done layouts and buttons. Still working on an easier events manager, images, rich-text widget, and menus. It natively supports getindex/setindex! style operation for configuring many of its features. For example, Label("")[:label] = "hello world", Label("")[:label,String] == "hello world"] and grid[1,2:3] = Button("Press me") or window = push!(Window("My Window"), BoxLayout(:h)). I'll post again when I'm nearly to a complete feature-set.

*you'll have to wait for the next version of IE for some of the features

@timholy
Copy link
Member Author

timholy commented Oct 15, 2013

@timholy All of those things have been possible in a browser for many years.

Hmm, last time I tried google docs none of that worked. Maybe that was a while ago :). If IPython would permit one to bind the space bar to a "pause/restart the video playback" (and the rest of those features) then I'd say that perhaps this is the way we should go.

@vtjnash, I hadn't realized you'd picked up Gtk again; I'll have to take a look sometime.

@JeffBezanson
Copy link
Member

I'm worried that Qt is both very large in itself, and will require huge amounts of wrapper code due to being C++.

I think many people have the requirements of (1) very easy to program, (2) performs well, (3) portable. @timholy is almost a perfect example of this, except he doesn't really need (1) but I assume would prefer it :)

I don't want to reinvent the wheel, but this particular wheel sucks.

For example, many people would benefit from being able to create simple Manipulate-style GUIs in 1 or 2 lines, that worked both locally and in the browser (when IPython support lands). This should be fully possible and seems like a good idea to me. Of course, if we could get all the features and performance we need in the browser I'd be willing to go browser-only with that, but that's up in the air. This functionality could potentially just be part of a "plotting package", but then "plotting" has to be quite broadly construed, since there's no reason everything has to look like a traditional plot. Ultimately I suspect "plotting" is not a useful abstraction and you want to think of it as "graphics". Then there should be a smooth path from that to slightly more complex GUIs --- it would be best not to have to switch to a totally different API to get more functionality. These requirements might seem unreasonable, but hey, I'm greedy.

@timholy
Copy link
Member Author

timholy commented Oct 15, 2013

I'm worried that Qt is both very large in itself, and will require huge amounts of wrapper code due to being C++.

My fear too. I had wondered about starting a QtLite (or QtCute) to see how much we really needed to wrap. Much of Qt may not be necessary since a lot of it is redundant with libuv. But these things have a tendency to expand over time as people need more stuff.

Portable & performant: definitely key requirements. These days I'm kinda bummed about Tk in both of those departments. If you're just showing one image in one window, Tk's performance seems fine (that is, with the rather serious exception of JuliaGraphics/Tk.jl#57), but even simple stuff like dragging a second window across the first one introduces weird latencies, etc. Theoretically I should just figure out what I need to do to fix those issues, but between limited time and a sense that maybe the better plan is to switch toolkits, I just haven't done that.

...he doesn't really need (1) but I assume would prefer it :)

I'm all in favor of easy!

Ultimately I suspect "plotting" is not a useful abstraction and you want to think of it as "graphics"

I've had the same sense, although perhaps that's because at this point I know the low-level stuff better than I understand Winston's internals.

@jverzani
Copy link
Member

One can already get at Qt via PyCall. I don't see why someone would undertake the work involved to do so directly from Julia, as in theory this access is as easy as installing Anaconda, then Pkg.add("PyCall"). The huge upside of @vtjnash 's work on Gtk is the integration with Cairo. The basic graphics of WInston will just work along with the GUI controls.

@timholy
Copy link
Member Author

timholy commented Oct 16, 2013

One can already get at Qt via PyCall. I don't see why someone would undertake the work involved to do so directly from Julia, as in theory this access is as easy as installing Anaconda, then Pkg.add("PyCall").

If we wanted to use QPainter as an alternative to Cairo, I wonder if the overhead of going through Python would be too large. Perhaps we could just wrap QPainter, and use PyCall for everything else?

But I'm excited about @vtjnash's Gtk work, so I plan to sit tight and see how that works out. As long as Gtk doesn't end up having its own share of major downsides, I'm all in favor of something that's ready rather than something that will take a lot of effort to get going.

@jverzani
Copy link
Member

In the PySide package there is an example of using pyqtgraph. This Python package uses QPainter, if I'm not mistaken . I think I noticed when I wrote that example that performance started to degrade somewhere between 10,000 and 100,000 points for a basic scatterplot. I'm not sure if that is due to pyqtgraph, QPainter, Python or PyCall.

@StefanKarpinski
Copy link
Member

Hard as it is to believe, I'm starting to feel like all the GUI toolkits fall short.

@timholy
Copy link
Member Author

timholy commented Oct 21, 2013

I did some profiling, and basically all the time is spent either in libpython or, for simple-plotting.jl, in a try/catch block in PyCall.jl. I don't think it reflects the performance of the underlying GUI toolkit.

@timholy timholy deleted the teh/graphics branch November 4, 2013 11:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants