python-concur icon indicating copy to clipboard operation
python-concur copied to clipboard

Create and/or Publish Complex Example Applications

Open potocpav opened this issue 5 years ago • 26 comments

Present these applications front-and-center on the homepage. Right now, the homepage contains just trivial usage examples, which really doesn't look too good. Could be inspired by the Streamlit homepage.

Contributions welcome.

potocpav avatar May 22 '20 10:05 potocpav

Ive actually been trying to build my application with concur for a while (currently using PySimpleGUI) , I would be willing to display it if you help me with some very basic things.

For instance I got this snippet:

import concur as c


def test():
	print("Orange")

def app():
	while True:
		key, event = yield from c.orr([
			c.button("test"),
			c.button(f"Banana"),

		])

		if key == "test":
			test()
		print("Clicked:", event)
		yield


c.main(app())

Now I would like to make test() open another window with some more buttons, how could I do that?

sla-te avatar Jun 04 '20 07:06 sla-te

Hi, sorry for the delay in answering.

The most straightforward way to achieve this is using a state variable for whether the window is open.

import concur as c

def test():
    return c.window("Window", c.orr([
        c.button("test-window"),
        c.button("Banana-window"),
        c.button("Close"),
        ]))

def app():
    window_open = False
    while True:
        key, event = yield from c.orr([
            c.button("Toggle window"),
            test() if window_open else c.nothing(),
        ])

        if key == "Toggle window":
            window_open = not window_open
        elif key == "Close":
            window_open = False

        print("Clicked:", key)
        yield

c.main(app())

I hope this is what you were looking for. Feel free to ask some more. I should be able to answer faster in the future :)

Edit: added a close button to the window.

potocpav avatar Jun 04 '20 13:06 potocpav

It would be great if you could share your application! I will be glad to review the code and/or help you with using Concur.

potocpav avatar Jun 04 '20 13:06 potocpav

Thanks for the snippet! Its almost what I am looking for, What I would need though is a "main" Gui which has some buttons, then if I click one of the buttons it will open another separate window, like starting a new feature. It shouldnt all be inside a "wrapper window" though but all free floating separate windows. As for the application I need some time to prepare it but we can share the whole gui part when its prepared.

sla-te avatar Jun 04 '20 16:06 sla-te

I haven't really used multiple separate OS windows. ImGui supports this use-case, see this issue. The video in the first comment may show what you want.

However, Concur doesn't support this ATM. I don't know how difficult would it be to implement, and how much would it complicate things. There may (or may not) be some subtleties with window position remembering, working on all platforms, etc.

If all you need is a file open/save dialog, then use wxPython.

While there are valid use-cases for multiple windows, a single window may be better from user's perspective. Gimp before 2.8 used multiple OS windows, and it wasn't really working too well. Blender is a complex single-window application with flexible docking. And web-based applications don't support multiple windows either.

potocpav avatar Jun 04 '20 19:06 potocpav

Its indeed the use case I am looking for though. It it worked on Windows that would be perfectly sufficient. Window positioning remembering would not be a big issue as well. Do you think you could throw out a quick and dirty solution for it?

sla-te avatar Jun 05 '20 09:06 sla-te

	key = yield from c.orr([

			c.main_menu_bar(widget=c.orr([
				c.menu(label="File", widget=c.orr([
					c.menu_item("New", "Ctrl+N"),
					c.menu_item("Open...", "Ctrl+O"),
					c.separator(),
					c.menu_item("Quit", "Ctrl+Q"),
				])),
			])),

			c.key_press("Quit", ord('Q'), ctrl=True),
			c.button("Banana"),
			c.button("Toggle window"),
			test() if window_open else c.nothing(),
		])

So this doesnt seem to drop any warning but if i do it like this:

	key, event = yield from c.orr([

			c.main_menu_bar(widget=c.orr([
				c.menu(label="File", widget=c.orr([
					c.menu_item("New", "Ctrl+N"),
					c.menu_item("Open...", "Ctrl+O"),
					c.separator(),
					c.menu_item("Quit", "Ctrl+Q"),
				])),
			])),

			c.key_press("Quit", ord('Q'), ctrl=True),
			c.button("Banana"),
			c.button("Toggle window"),
			test() if window_open else c.nothing(),
		])

The ide will mark it all in yellow and say "need more values to unpack", how do I manage that?

sla-te avatar Jun 05 '20 11:06 sla-te

I don't see a difference between those two snippets. Did you accidentally copy the same thing twice?

potocpav avatar Jun 05 '20 11:06 potocpav

My bad, copy paste error, check now

sla-te avatar Jun 05 '20 11:06 sla-te

It runs fine when I try it. Is it possible that the analysis done by IDE is incorrect? What IDE do you use, and how does it analyze the code?

It's also possible that the type annotations in core.py are buggy, removing them may work. I will remove them in master if it fixes the issue.

It may be possible to get rid of the warning by some reformatting, such as

ret = yield from ...
key, event = ret[0], ret[1]

but that's definitely quite ugly.

potocpav avatar Jun 05 '20 12:06 potocpav

yeah, thats what i tried too,, then you get this one: image :D

sla-te avatar Jun 05 '20 12:06 sla-te

Not sure if it is incorrect, im using Pycharm

sla-te avatar Jun 05 '20 12:06 sla-te

Also im looking for a replacement for "PopupGetFile" in PySimpleGUI, any suggestions? Basically just a file brower with which a user can select a file and then its path will be returned.

sla-te avatar Jun 05 '20 12:06 sla-te

About the multiple windows, I found a more in-depth explanation of what needs to be done. It looks like it requires quite involved changes to the GLFW integration layer, and the API isn't stable.

The required changes are implemented in the example GLFW backend in C++ (imgui_impl_glfw.cpp). However, Concur uses a different GLFW backend code written in Python, so the code would have to be re-implemented.

The C++ integration has 850 LOC, and a whole bunch of new functions would have to be exposed through Cython. It is not something I have time to do. And I don't have a Windows installation anyways to test it.

potocpav avatar Jun 05 '20 12:06 potocpav

Ok, thats not a big problem, I have thought about it and I could do it inside a wrapper window.

sla-te avatar Jun 05 '20 12:06 sla-te

I used in wxPython for a file-open dialog, like in this stackoverflow answer. There may be better options on Windows, idk.

potocpav avatar Jun 05 '20 12:06 potocpav

I tested PyCharm, and it is definitely a bug in their handling of generators. I don't think the exact issue is in their bug tracker. It can be replicated by this:

a, b = yield from c.event((123, 456))

and c.event is a dead-simple function with no type annotations. I would suggest just disabling the warning and/or reporting the bug to PyCharm.

potocpav avatar Jun 05 '20 13:06 potocpav

Awesome! Thanks for figuring that out. I will just wrap away the main gui window in a function and have it return the window, that way the whole main loop wont be yellow ^^

sla-te avatar Jun 05 '20 13:06 sla-te

Ok, so now it gets a little tricky. I have a class or lets call it a feature, that I would want to start via click on a button. This is the way I would think of handling it (with the idea to open a new window from within the NiceFeature class inside the thread but that didnt go too well :D):

	elif event == "Nice Feature":
			from src.features.nice_feature.nice_feature import NiceFeature
			t_nice_feature= Thread(target=NiceFeature(settings).run(), daemon=True)
			t_nice_feature.start()
			running_features.append({"feature_name": "Nice Feature", "timestamp": datetime.datetime.now(), "thread_obj": t_nice_feature})

Now before starting the feature, I must give it some settings which it needs, to know what to do. So on clicking the button a new window should open from within which I can define the required settings and then click "start", which then in order should call the run() function of the class NiceFeature to start execution.

sla-te avatar Jun 05 '20 17:06 sla-te

Ok, so I did some trial and error and now tried to create a separate file for every feature containing functions, that will return new customized windows for every function. Then imported all these functions in to the main gui script and ran. So far so good. - Now inside of the NiceFeature class a ThreadPoolExecutor is started and apparently after starting the feature the main gui will be frozen, any suggestions?

sla-te avatar Jun 05 '20 18:06 sla-te

I created a repository to illustrate the problem (and invited you as collaborator, feel free to push changes to master): https://github.com/chwba/concur_gui_test

sla-te avatar Jun 05 '20 18:06 sla-te

I pushed some changes into the repo. Hopefully, it will be helpful for you to go through the commits :-) . Play around with it.

In the last change, I tried to show how the main event loop can be split into multiple loops if the application gets too big. State can be also broken up into several pieces using nested classes, but I didn't do it since the state is so small here.

There is a weird thing going on where the state is mutated in nice_feature_gui, but then also returned. I normally deepcopy state before handling it to functions, but deepcopy doesn't work for futures, and it may require a custom __deepcopy__ override. I didn't do that to keep the code cleaner. If you run into trouble with that, feel free discuss the problems.

potocpav avatar Jun 06 '20 17:06 potocpav

Big hero bro 🗡️ :D - Will tinker around with it soon!

sla-te avatar Jun 06 '20 20:06 sla-te

Ok, I see one thing. as of now executor.shutdown is not being called and afaik if not called, it will not free the resources of the submitted futures which in case we submit thousands of futures will lead to severe performance problems. Please correct me if im wrong but this was my experience from working with the executor in the past.

sla-te avatar Jun 07 '20 13:06 sla-te

I pushed all my attempts to "hack around" the problem to master, maybe you can find a solution

sla-te avatar Jun 07 '20 15:06 sla-te

Let's move this discussion to your repo's issue tracker https://github.com/chwba/concur_gui_test/issues/1

potocpav avatar Jun 08 '20 08:06 potocpav