Converting embedded JSON into flat table
I don't know anything about tkinter, so I'm just going to look at your flatten function.

I'm going to start with some overarching comments. When checking for the type of something, use  isinstance instead of type(x) is some_type. Secondly, when you have a trivial loop of the form

list_ = []
for x in iterable:
    list_.append(function(x))


You almost always want to turn it into a list comprehension

list_ = [function(x) for x in iterable]


You have an unnecessary dict.copy which is definitely going to slow things down if you start having very large files.

You can get rid of the for i in range(len(data)) and just use for item in data.

I don't like that out isn't a local variable/parameter, and I find it a bit hacky that it is modified inside of flatten2 without being passed as a parameter.  I think a better idea is to use an input parameter. This might also help speed things up, as Python accesses locals faster than nonlocals.

Now you also have a minor correctness issue - you only handle dict and list, but what if there were a tuple inside? Some user defined type that quacks like a dict? Admittedly if you're parsing json that is unlikely, but this would be a fairly useful general utility to flatten all sorts of nested mappings.  There are all sorts of ways to handle this, but the easiest might be to ask forgiveness instead of permission

try:
    for key, value in x.items():
        # your dict stuff here
except (ValueError, AttributeError): # oh this doesn't support unpacking/the items() method
    for item in x: # treat it like a list


Not necessarily a perfect solution, but worth considering.

I doubt this is going to help a ton with speed. Short of parallelising this (and I don't think Python would do that effectively with either threads or processes) I'm not seeing a good solution.

One last minor thing - if you have a large and deeply nested json file this might choke with a recursion error. You could fix that by using a list or a queue and keep adding items to it as they're discovered.  Something like this (sketched, may not work right away) might work

to_flatten = [(item, '') for item in y]
for item, name in to_flatten:
    if isinstance(item, dict):
       for key, value in item.items():
            if key == "name":
                to_flatten.append((item["value"], name + item[key] + '_'))
            else:
                to_flatten.append((item[key], name + key + '_'))
    elif isinstance(x, (list, tuple)):
       for member in item:
           to_flatten.append((member, name + '_'))
    else:
        result_dict[name[:-1]] = item


This may also help with speed - I honestly don't know.

One last note - like with most languages, string concatenation is slow in Python. In CPython, the peephole optimizer does some magic with just 2 strings (I wish I could find the source for this) but doesn't for more than that. And according to PEP8,


  For example, do not rely on CPython's efficient implementation of in-place string concatenation for statements in the form a += b or a = a + b. This optimization is fragile even in CPython ... In performance sensitive parts of the library, the ''.join() form should be used instead.


(emphasis and code-formatting added)

You might be able to get a speedup by changing your string concatenation method.

to_flatten.append((item["value"], ''.join([name, item[key], '_'])))