2

I am new to python GUI and have never used python GUI before. I just decided to gave a try. this is my function which convert local datetime to epoch, eg.py is the filename where both this functions are

def epochConverter(a):
    return datetime(*a).timestamp()

This functions takes two parameters of datetime and returns in timestamp (milliseconds)

def DateExtraction(fromTime, toTime):
    convertedFromTime = int(epochConverter(fromTime)*1000)
    convertedtoTime = int(epochConverter(toTime)*1000)

    time = {'from':convertedFromTime,'to':convertedtoTime}
    return time

this works as expected

print(DateExtraction((2018,6,8,0,0,0), (2018,6,8,1,0,0)))

Now, I wanted to implement this in python GUI and I am using appjar library. This simple GUI code looks like this

from appJar import gui
from eg import DateExtraction

class MyApplication():
    # Build the GUI
    def Prepare(self, app):
        # Form GUI
        app.setTitle("Simple Application")
        app.setFont(16)
        app.setStopFunction(self.BeforeExit)

        app.addLabel('oneTime',"From Time:", 0, 0)
        app.addEntry("fromTime", 0, 1)
        app.addLabel('twoTime',"To Time:", 1, 0)
        app.addEntry("toTime", 1, 1)
        app.addButtons(["Submit"], self.Submit, colspan=2)
        return app


    def Start(self):
        # Creates a UI
        app = gui()
        app = self.Prepare(app)
        self.app = app
        app.go()

    def BeforeExit(self):
        return self.app.yesNoBox("Confirm Exit", "Are you sure you want to exit?")


    def Submit(self, btnName):
        if btnName == "Submit":
            timefrom = self.app.getEntry("fromTime")
            timeto = self.app.getEntry("toTime")

            DateExtraction(timefrom, timeto)

if __name__ == '__main__':
    App = MyApplication()
    App.Start()

When the GUI runs, I fill both text fields as it is

2018,6,8,0,0,0
2018,6,8,1,0,0

and it throws error

TypeError: function takes at most 9 arguments (14 given)

I also tried, just in case

(2018,6,8,0,0,0)
(2018,6,8,1,0,0)

and again throws the same error

type error, functions takes bla bla arguments (bla bla given)

I am new in python GUI and any kind of suggestions is welcome. Also any suggestions about tkinter to implement above functions would be also helpful.

2
  • Unless appJar.gui is a thin wrapper around tkinter or something (which it might be—I honestly have no idea), I don't think you want the tkinter tag here. Commented Jun 19, 2018 at 21:39
  • 1
    @abarnert appJar is built on tkinter but in this case the problem seems more based on Python types then the gui itself so could still remove it (I'd personally leave it just so people who use tkinter see this/find in their searches). Commented Jun 19, 2018 at 21:41

1 Answer 1

2

I don't know anything about appJar, but the contents of a text entry field are almost certainly going to be a string, not a tuple of numbers. So, instead of calling epochConverter((2018,6,8,0,0,0)), you end up calling epochConverter("(2018,6,8,0,0,0)"), which obviously isn't going to work.

The specific problem is that *a. For a tuple of 6 numbers, that turns into 6 arguments; for a string of 14 characters, it turns into 14 arguments.

Anyway, you need to write some code that takes input string, and parses it into the right format.


One way to do this, albeit a pretty hacky way, is to use literal_eval, which takes any string that works as a Python source-code literal and turns it into the equivalent value:

timefrom = ast.literal_eval(self.app.getEntry("fromTime"))

You'd probably want to add some error handling, of course:

try:
    timefrom = ast.literal_eval(self.app.getEntry("fromTime"))
except SyntaxError as e:
    # pop up an error box, or whatever seems appropriate

Also, even if literal_eval succeeds, that just means you had some valid Python valid, not necessarily a tuple of 6 integers—it'll succeed just as well with, say, a set of two strings and a complex number.


A cleaner way to do this is to write a parser for your specific format. This may sound a bit scary, but your format is pretty trivial: you have to have exactly 6 integers, with commas in between, right? So:

def parse_input_date(s):
    parts = s.split(',')
    if len(parts) != 6: raise ValueError(f'Wrong number of parts: {len(parts)} instead of 6')
    return [int(part) for part in parts]

So now:

timefrom = parse_input_date(self.app.getEntry("fromTime"))

And again, you'll want some error handling. In this case, an invalid string is going to give you a ValueError instead of a SyntaxError, but otherwise, it's the same.

Of course, even though now we can be sure we have a list of six numbers, you can still get an error from the date parsing—e.g., the user could have asked for 2018,40,5,0,0,0.


You might also want to consider moving the conversion logic into epochConverter or DateExtraction instead of the GUI. \

For example, imagine that you wanted to use the same "engine" code with a command-line tool. That command-line tool is going to get its arguments from sys.argv, or input(), or similar, so it's also going to end up getting a string, in the same format as the GUI entry, right? So you'll probably want it to share the same string-to-tuple conversion logic.

Sign up to request clarification or add additional context in comments.

1 Comment

thank you, I will try and will let you know, how it goes :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.