Python Forum
WxPython in web with a cgi server
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
WxPython in web with a cgi server
#1
HELLO,
My name is Jayson,
I am new to this forum and thought it would unravel my issue:

A web based GUI in a python script???
I always need to attach a display by the end and I cannot get through...

HERE WE GO:
I have a website on a gcloud ubuntu 18 virtual machine (g1). https://35.236.122.135
The site is slung from a webserver on port 443 for webrtc with cgi via https://35.236.122.135/webserver3.py
In https://35.236.122.135/cgi-bin/ I run python scripts, also deeper
In https://35.236.122.135/cgi-bin/lftr/music/ I have 4 scripts that are relevant

1: https://35.236.122.135/cgi-bin/lftr/musi..._PLAYER.py
2: https://35.236.122.135/cgi-bin/lftr/musi...D_AUDIO.py
3: https://35.236.122.135/cgi-bin/lftr/musi...TO_MIDI.py
4: https://35.236.122.135/cgi-bin/lftr/music/PLAY_MIDI.py

They are not just up, they will run in position.

Also. now. when I run it by going to https://35.236.122.135/cgi-bin/lftr/musi..._PLAYER.py ; or cd /var/www/cgi-bin/lftr/music then sudo python3 AUDIO_TO_MIDI_PLAYER.py


I GET MY ERROR: NO DISPLAY for the website

"Unable to access the X Display, is $DISPLAY set Properly?"

would anyone be able to assist me in my quest to have this work?...
Reply
#2
First url is not secure. didn't attempt anymore.
Post code here in code tags see: BBcode
Reply
#3
Ok...will do...jayt. I have a self signed cert for my webserver to get https and run webrtc.
Anyway...the files. On Linux in the structure outlined in the first post:

webserver3.py
import os, sys
from http.server import HTTPServer, CGIHTTPRequestHandler
import ssl
webdir = '/var/www/'
port = 443
os.chdir(webdir)
srvaddr=('', port)
srvobj = HTTPServer(srvaddr, CGIHTTPRequestHandler)
srvobj.socket = ssl.wrap_socket (srvobj.socket, keyfile='/var/security/35.236.122.135.key', certfile='/var/security/35.236.122.135.crt', server_side=True)
CGIHTTPRequestHandler.have_fork=False # Force the use of a subprocess
srvobj.serve_forever()
1:AUDIO_TO_MIDI_PLAYER.py
#!usr/bin/env python3
import cgitb
cgitb.enable
import os

import wx
import os
class MyForm(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Launch Scripts")
        panel = wx.Panel(self, wx.ID_ANY)
        sizer = wx.BoxSizer(wx.VERTICAL)
        buttonA = wx.Button(panel, id=wx.ID_ANY, label="App A", name="GETandUPLOAD_AUDIO")
        buttonB = wx.Button(panel, id=wx.ID_ANY, label="App B", name="CONVERT_AUDIO_TO_MIDI")
        buttonC = wx.Button(panel, id=wx.ID_ANY, label="App C", name="PLAY_MIDI")
        buttons = [buttonA, buttonB, buttonC]

        for button in buttons:
            self.buildButtons(button, sizer)

        panel.SetSizer(sizer)

    def buildButtons(self, btn, sizer):
        btn.Bind(wx.EVT_BUTTON, self.onButton)
        sizer.Add(btn, 0, wx.ALL, 5)

    def onButton(self, event):
        button = event.GetEventObject()

        os.system('python {}.py'.format(button.GetName()))

        button_id = event.GetId()
        button_by_id = self.FindWindowById(button_id)
        print ("The button you pressed was labeled: " + button_by_id.GetLabel())
        print ("The button's name is " + button_by_id.GetName())

# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()


print ('''Content-Type: text/html''')
print
print ('''<html>












<?php  ?>
<html>
<head>
    <meta charset="UTF-8">
    <title>MUSIC - audio to midi player</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  </head>
<style>* {
  padding: 0;
  margin: 0;
}
a {
  color: #337ab7;
}
p {
  margin-top: 1rem;
}
a:hover {
  color:#23527c;
}
a:visited {
  color: #8d75a3;
}
body {
  margin: 1rem;
  padding: 1rem;
  font-family: sans-serif;
  max-width: 28rem;
  margin: 0 auto;
  position: relative;
}
#controls {
  display: flex;
  margin-top: 2rem;
}
button {
  flex-grow: 1;
  height: 2.5rem;
  min-width: 2rem;
  border: none;
  border-radius: 0.15rem;
  background: #ed341d;
  margin-left: 2px;
  box-shadow: inset 0 -0.15rem 0 rgba(0, 0, 0, 0.2);
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  color:#ffffff;
  font-weight: bold;
  font-size: 1rem;
}
button:hover, button:focus {
  outline: none;
  background: #c72d1c;
}
button::-moz-focus-inner {
  border: 0;
}
button:active {
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
  line-height: 3rem;
}
button:disabled {
  pointer-events: none;
  background: lightgray;
}
button:first-child {
  margin-left: 0;
}
audio {
  display: block;
  width: 100%;
  margin-top: 0.2rem;
}
li {
  list-style: none;
  margin-bottom: 1rem;
}
#formats {
  margin-top: 0.5rem;
  font-size: 80%;
}
</style>''')
2: GETandUPLOAD_AUDIO.py
#!usr/bin/env python3
import cgitb
cgitb.enable

print ('''Content-Type: text/html''')
print
print ('''<html>













<html>
<body>
    <h1>RECORD AUDIO .wav to convert to midi</h1>
    
    <div id="controls">
  	 <button id="recordButton">Record</button>
  	 <button id="pauseButton" disabled>Pause</button>
  	 <button id="stopButton" disabled>Stop</button>
    </div>
    <div id="formats">Format: start recording to see sample rate</div>
  	<h3>Recordings</h3>
  	<ol id="recordingsList"></ol>

   
  	<script src="https://cdn.rawgit.com/mattdiamond/Recorderjs/08e7abd9/dist/recorder.js"></script>
  	<script>URL = window.URL || window.webkitURL;
var gumStream; 						//stream from getUserMedia()
var rec; 							//Recorder.js object
var input; 							//MediaStreamAudioSourceNode we'll be recording

// shim for AudioContext when it's not avb. 
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext //audio context to help us record

var recordButton = document.getElementById("recordButton");
var stopButton = document.getElementById("stopButton");
var pauseButton = document.getElementById("pauseButton");

//add events to those 2 buttons
recordButton.addEventListener("click", startRecording);
stopButton.addEventListener("click", stopRecording);
pauseButton.addEventListener("click", pauseRecording);

function startRecording() {
	console.log("recordButton clicked");

	/*
		Simple constraints object, for more advanced audio features see
		https://addpipe.com/blog/audio-constraints-getusermedia/
	*/
    
    var constraints = { audio: true, video:false }

 	/*
    	Disable the record button until we get a success or fail from getUserMedia() 
	*/

	recordButton.disabled = true;
	stopButton.disabled = false;
	pauseButton.disabled = false

	/*
    	We're using the standard promise based getUserMedia() 
    	https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
	*/

	navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
		console.log("getUserMedia() success, stream created, initializing Recorder.js ...");

		/*
			create an audio context after getUserMedia is called
			sampleRate might change after getUserMedia is called, like it does on macOS when recording through AirPods
			the sampleRate defaults to the one set in your OS for your playback device

		*/
		audioContext = new AudioContext();

		//update the format 
		document.getElementById("formats").innerHTML="Format: 1 channel pcm @ "+audioContext.sampleRate/1000+"kHz"

		/*  assign to gumStream for later use  */
		gumStream = stream;
		
		/* use the stream */
		input = audioContext.createMediaStreamSource(stream);

		/* 
			Create the Recorder object and configure to record mono sound (1 channel)
			Recording 2 channels  will double the file size
		*/
		rec = new Recorder(input,{numChannels:1})

		//start the recording process
		rec.record()

		console.log("Recording started");

	}).catch(function(err) {
	  	//enable the record button if getUserMedia() fails
    	recordButton.disabled = false;
    	stopButton.disabled = true;
    	pauseButton.disabled = true
	});
}

function pauseRecording(){
	console.log("pauseButton clicked rec.recording=",rec.recording );
	if (rec.recording){
		//pause
		rec.stop();
		pauseButton.innerHTML="Resume";
	}else{
		//resume
		rec.record()
		pauseButton.innerHTML="Pause";

	}
}

function stopRecording() {
	console.log("stopButton clicked");

	//disable the stop button, enable the record too allow for new recordings
	stopButton.disabled = true;
	recordButton.disabled = false;
	pauseButton.disabled = true;

	//reset button just in case the recording is stopped while paused
	pauseButton.innerHTML="Pause";
	
	//tell the recorder to stop the recording
	rec.stop();

	//stop microphone access
	gumStream.getAudioTracks()[0].stop();

	//create the wav blob and pass it on to createDownloadLink
	rec.exportWAV(createDownloadLink);
}

function createDownloadLink(blob) {
	
	var url = URL.createObjectURL(blob);
	var au = document.createElement('audio');
	var li = document.createElement('li');
	var link = document.createElement('a');

	//name of .wav file to use during upload and download (without extendion)
	var filename = 'Recording';

	//add controls to the <audio> element
	au.controls = true;
	au.src = url;

	//save to disk link
	link.href = url;
	link.download = filename+".wav"; //download forces the browser to donwload the file using the  filename
	link.innerHTML = "Save to disk";

	//add the new audio element to li
	li.appendChild(au);
	
	//add the filename to the li
	li.appendChild(document.createTextNode(filename+".wav "))

	//add the save to disk link to li
	li.appendChild(link);
	
	//upload link
	var upload = document.createElement('a');
	upload.href="#";
	upload.innerHTML = "Upload";
	upload.addEventListener("click", function(event){
		  var xhr=new XMLHttpRequest();
		  xhr.onload=function(e) {
		      if(this.readyState === 4) {
		          console.log("Server returned: ",e.target.responseText);
		      }
		  };
		  var fd=new FormData();
		  fd.append("audio_data",blob, filename);
		  xhr.open("POST","upload.php",true);
		  xhr.send(fd);
	})
	li.appendChild(document.createTextNode (" "))//add a space in between
	li.appendChild(upload)//add the upload link to li

	//add the li element to the ol
	recordingsList.appendChild(li);
}</script>
    
  </body>
</html>''')


print ('''''')
print ('''''')
print ('''''')
print ('''''')
print ('''<html><h1>Directory Listing:</h1></html>''')
print ('''<html><h1>/var/www/cgi-bin/lftr/</h1></html>''')
print ('''<html><h1>[music][audio][midi]</h1></html>''')

folder = os.listdir("/var/www/cgi-bin/lftr/music/")
audiofolder = os.listdir("/var/www/cgi-bin/lftr/music/audio")
midifolder = os.listdir("/var/www/cgi-bin/lftr/music/midi")

print ('''''')
print ('''''')
print ('''''')
print ('''''')
print (folder)
print (audiofolder)
print (midifolder)
3: CONVERT_AUDIO_TO_MIDI.py
#!usr/bin/env python3
import cgitb
cgitb.enable

print ('''Content-Type: text/html''')
print
print ('''<html>











</html>''')
print ('''''')
print ('''''')
print ('''''')
print ('''''')
print ('''<html><h1>Directory Listing:</h1></html>''')
print ('''<html><h1>/var/www/cgi-bin/lftr/</h1></html>''')
print ('''<html><h1>[music][audio][midi]</h1></html>''')

folder = os.listdir("/var/www/cgi-bin/lftr/music/")
audiofolder = os.listdir("/var/www/cgi-bin/lftr/music/audio")
midifolder = os.listdir("/var/www/cgi-bin/lftr/music/midi")

print ('''''')
print ('''''')
print ('''''')
print ('''''')
print (folder)
print (audiofolder)
print (midifolder)


print ('''''')
print ('''''')
print ('''''')
print ('''''')

print ('''''')
print ('''''')
print ('''''')
print ('''''')



# CREATED: 11/9/15 3:57 PM by Justin Salamon <[email protected]>

import librosa
import vamp
import argparse
import os
import numpy as np
from midiutil.MidiFile import MIDIFile
from scipy.signal import medfilt
import jams
import __init__

'''
Extract the melody from an audio file and convert it to MIDI.

The script extracts the melody from an audio file using the Melodia algorithm,
and then segments the continuous pitch sequence into a series of quantized
notes, and exports to MIDI using the provided BPM. If the --jams option is
specified the script will also save the output as a JAMS file. Note that the
JAMS file uses the original note onset/offset times estimated by the algorithm
and ignores the provided BPM value.

Note: Melodia can work pretty well and is the result of several years of
research. The note segmentation/quantization code was hacked in about 30
minutes. Proceed at your own risk... :)

usage: audio_to_midi_melodia.py [-h] [--smooth SMOOTH]
                                [--minduration MINDURATION] [--jams]
                                infile outfile bpm


Examples:
python audio_to_midi_melodia.py --smooth 0.25 --minduration 0.1 --jams
                                ~/song.wav ~/song.mid 60
'''


def save_jams(jamsfile, notes, track_duration, orig_filename):

    # Construct a new JAMS object and annotation records
    jam = jams.JAMS()

    # Store the track duration
    jam.file_metadata.duration = track_duration
    jam.file_metadata.title = orig_filename

    midi_an = jams.Annotation(namespace='pitch_midi',
                              duration=track_duration)
    midi_an.annotation_metadata = \
        jams.AnnotationMetadata(
            data_source='audio_to_midi_melodia.py v%s' % __init__.__version__,
            annotation_tools='audio_to_midi_melodia.py (https://github.com/'
                             'justinsalamon/audio_to_midi_melodia)')

    # Add midi notes to the annotation record.
    for n in notes:
        midi_an.append(time=n[0], duration=n[1], value=n[2], confidence=0)

    # Store the new annotation in the jam
    jam.annotations.append(midi_an)

    # Save to disk
    jam.save(jamsfile)


def save_midi(outfile, notes, tempo):

    track = 0
    time = 0
    midifile = MIDIFile(1)

    # Add track name and tempo.
    midifile.addTrackName(track, time, "MIDI TRACK")
    midifile.addTempo(track, time, tempo)

    channel = 0
    volume = 100

    for note in notes:
        onset = note[0] * (tempo/60.)
        duration = note[1] * (tempo/60.)
        # duration = 1
        pitch = note[2]
        midifile.addNote(track, channel, pitch, onset, duration, volume)

    # And write it to disk.
    binfile = open(outfile, 'wb')
    midifile.writeFile(binfile)
    binfile.close()


def midi_to_notes(midi, fs, hop, smooth, minduration):

    # smooth midi pitch sequence first
    if (smooth > 0):
        filter_duration = smooth  # in seconds
        filter_size = int(filter_duration * fs / float(hop))
        if filter_size % 2 == 0:
            filter_size += 1
        midi_filt = medfilt(midi, filter_size)
    else:
        midi_filt = midi
    # print(len(midi),len(midi_filt))

    notes = []
    p_prev = None
    duration = 0
    onset = 0
    for n, p in enumerate(midi_filt):
        if p == p_prev:
            duration += 1
        else:
            # treat 0 as silence
            if p_prev > 0:
                # add note
                duration_sec = duration * hop / float(fs)
                # only add notes that are long enough
                if duration_sec >= minduration:
                    onset_sec = onset * hop / float(fs)
                    notes.append((onset_sec, duration_sec, p_prev))

            # start new note
            onset = n
            duration = 1
            p_prev = p

    # add last note
    if p_prev > 0:
        # add note
        duration_sec = duration * hop / float(fs)
        onset_sec = onset * hop / float(fs)
        notes.append((onset_sec, duration_sec, p_prev))

    return notes


def hz2midi(hz):

    # convert from Hz to midi note
    hz_nonneg = hz.copy()
    idx = hz_nonneg <= 0
    hz_nonneg[idx] = 1
    midi = 69 + 12*np.log2(hz_nonneg/440.)
    midi[idx] = 0

    # round
    midi = np.round(midi)

    return midi


def audio_to_midi_melodia(infile, outfile, bpm, smooth=0.25, minduration=0.1,
                          savejams=False):

    # define analysis parameters
    fs = 44100
    hop = 128

    # load audio using librosa
    print("Loading audio...")
    data, sr = librosa.load(infile, sr=fs, mono=True)
 	
    # extract melody using melodia vamp plugin
    print("Extracting melody f0 with MELODIA...")
    melody = vamp.collect(data, sr, "mtg-melodia:melodia",
                          parameters={"voicing": 0.2})

    # hop = melody['vector'][0]
    pitch = melody['vector'][1]

    # impute missing 0's to compensate for starting timestamp
    pitch = np.insert(pitch, 0, [0]*8)

    # debug
    # np.asarray(pitch).dump('f0.npy')
    # print(len(pitch))

    # convert f0 to midi notes
    print("Converting Hz to MIDI notes...")
    midi_pitch = hz2midi(pitch)

    # segment sequence into individual midi notes
    notes = midi_to_notes(midi_pitch, fs, hop, smooth, minduration)

    # save note sequence to a midi file
    print("Saving MIDI to disk...")
    save_midi(outfile, notes, bpm)

    if savejams:
        print("Saving JAMS to disk...")
        jamsfile = outfile.replace(".mid", ".jams")
        track_duration = len(data) / float(fs)
        save_jams(jamsfile, notes, track_duration, os.path.basename(infile))

    print("Conversion complete.")


if __name__ == "__main__":

  

    audio_to_midi_melodia(Recording.wav, Recording.mid, 87,
                          smooth=.25, minduration=.2)
4: PLAY_MIDI.py
#!usr/bin/env python3
import cgitb
cgitb.enable
import mido
msg = mido.Message('note_on", note=60)
msg.type
msg.note
msg.bytes()
msg.copy(channel=2)
port = mido.open_output('Port Name')
port.send(msg)
with mido.open_input() as inport:
    for msg in inport:
        print(msg)

mid = mido.MidiFile('Recording.mid')
for msg in mid.play():
    port.send(msg)
I know I have some work to do but the concept is hurt too
Reply
#4
While there are other errors the main issue still stands with script 1: AUDIO_TO_MIDI_PLAYER.py. When it runs it doesn't have a display.....[Image: view?usp=drivesdk]
Reply
#5
I have set up an environment and will see If I can be of service, no promises, and it will take some time to familiarize myself with your code.
I won't be able to run though because even though I have what is supposed to be a good install of wxpython on my Linux Mint environment, I haven't been able to successfully use it. I am quite familiar with the phoenix version and have used it extensively on MS windows, but not here.

I don't expect I will respond again on this until some time tomorrow.

Perhaps someone else in a better position to help will respond before then.
Reply
#6
Yes...it was some hours of compiling on a g1 for wxPython Phoenix in ubuntu18 I used pip3 install mostly
Reply
#7
I suppose I am looking for a Display Back-end. Similar to GTK's Broadwayd. https://developer.gnome.org/gtk3/stable/broadwayd.html
Through my research i have found ipython and it may be relevent if i rewrite my script some.
https://ipython.org/ipython-doc/3/intera...th-ipython
Reply
#8
I stopped playing this after mucking around once again, trying to get wxpython to install properly.
It installs, but is not usable.
Reply
#9
Yes, Hello again ---Jayson:

wxPython will work in with IPython in Python3. Especially, in deb or ubuntu

and this will be my direction, however the same problem exists. My x-display in web.

I will post again as this thread continues, with a simple script that will have the same issue. the x display.

Ok, well here we go: IPython
sudo nohup python3 /var/www/webserver3.py &
import os, sys
from http.server import HTTPServer, CGIHTTPRequestHandler
import ssl
webdir = '/var/www/'
port = 443
os.chdir(webdir)
srvaddr=('', port)
srvobj = HTTPServer(srvaddr, CGIHTTPRequestHandler)
srvobj.socket = ssl.wrap_socket (srvobj.socket, keyfile='/var/security/35.236.122.135.key', certfile='/var/security/35.236.122.135.crt', server_side=True)
CGIHTTPRequestHandler.have_fork=False # Force the use of a subprocess
srvobj.serve_forever()
sudo python3 /var/www/cgi-bin/lftr/wxgui.py
#!/usr/bin/env python3
import cgitb
cgitb.enable
"""
A Simple wx example to test IPython's event loop integration.

To run this do:

In [5]: %gui wx  # or start IPython with '--gui wx'

In [6]: %run gui-wx.py

Ref: Modified from wxPython source code wxPython/samples/simple/simple.py
"""

import wx


class MyFrame(wx.Frame):
    """
    This is MyFrame.  It just shows a few controls on a wxPanel,
    and has a simple menu.
    """
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, -1, title,
                          pos=(150, 150), size=(350, 200))

        # Create the menubar
        menuBar = wx.MenuBar()

        # and a menu
        menu = wx.Menu()

        # add an item to the menu, using \tKeyName automatically
        # creates an accelerator, the third param is some help text
        # that will show up in the statusbar
        menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample")

        # bind the menu event to an event handler
        self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT)

        # and put the menu on the menubar
        menuBar.Append(menu, "&File")
        self.SetMenuBar(menuBar)

        self.CreateStatusBar()

        # Now create the Panel to put the other controls on.
        panel = wx.Panel(self)

        # and a few controls
        text = wx.StaticText(panel, -1, "Hello World!")
        text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
        text.SetSize(text.GetBestSize())
        btn = wx.Button(panel, -1, "Close")
        funbtn = wx.Button(panel, -1, "Just for fun...")

        # bind the button events to handlers
        self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, btn)
        self.Bind(wx.EVT_BUTTON, self.OnFunButton, funbtn)

        # Use a sizer to layout the controls, stacked vertically and with
        # a 10 pixel border around each
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(text, 0, wx.ALL, 10)
        sizer.Add(btn, 0, wx.ALL, 10)
        sizer.Add(funbtn, 0, wx.ALL, 10)
        panel.SetSizer(sizer)
        panel.Layout()


    def OnTimeToClose(self, evt):
        """Event handler for the button click."""
        print("See ya later!")
        self.Close()

    def OnFunButton(self, evt):
        """Event handler for the button click."""
        print("Having fun yet?")


class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, "Simple wxPython App")
        self.SetTopWindow(frame)

        print("Print statements go to this stdout window by default.")

        frame.Show(True)
        return True


if __name__ == '__main__':

    app = wx.GetApp()
    if app is None:
        app = MyApp(redirect=False, clearSigInt=False)
    else:
        frame = MyFrame(None, "Simple wxPython App")
        app.SetTopWindow(frame)
        print("Print statements go to this stdout window by default.")
        frame.Show(True)

    try:
        from IPython.lib.inputhook import enable_gui
        enable_gui('wx', app)
    except ImportError:
        app.MainLoop()
now this code: will run IPython in a .py script on the cgi-server
#!/usr/bin/env python3
import cgitb
cgitb.enable
import IPython
IPython.start_ipython(argv=[])

I hope we still can have an open mind about this being fun and useful structure to run interactive web gui scripting which would be a PLUS...


and this becomes a complicated question: b/c sudo IPython /var/www/cgi-bin/lftr/wxgui.py --gui=wx
can be run as something like this: sudo python3 /var/www/cgi-bin/lftr/wxgui.py if it is including some IPython ----
#!/usr/bin/env python3
import cgitb
cgitb.enable

import IPython
IPython.start_ipython(argv=[]) # this will start IPython, however i am unsure how to input the entire script

import IPython.display #this will access  display for a gui of wx hopefully
gui=wx #incorrect code

import wx


class MyFrame(wx.Frame):
    """
    This is MyFrame.  It just shows a few controls on a wxPanel,
    and has a simple menu.
    """
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, -1, title,
                          pos=(150, 150), size=(350, 200))

        # Create the menubar
        menuBar = wx.MenuBar()

        # and a menu
        menu = wx.Menu()

        # add an item to the menu, using \tKeyName automatically
        # creates an accelerator, the third param is some help text
        # that will show up in the statusbar
        menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample")

        # bind the menu event to an event handler
        self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT)

        # and put the menu on the menubar
        menuBar.Append(menu, "&File")
        self.SetMenuBar(menuBar)

        self.CreateStatusBar()

        # Now create the Panel to put the other controls on.
        panel = wx.Panel(self)

        # and a few controls
        text = wx.StaticText(panel, -1, "Hello World!")
        text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
        text.SetSize(text.GetBestSize())
        btn = wx.Button(panel, -1, "Close")
        funbtn = wx.Button(panel, -1, "Just for fun...")

        # bind the button events to handlers
        self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, btn)
        self.Bind(wx.EVT_BUTTON, self.OnFunButton, funbtn)

        # Use a sizer to layout the controls, stacked vertically and with
        # a 10 pixel border around each
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(text, 0, wx.ALL, 10)
        sizer.Add(btn, 0, wx.ALL, 10)
        sizer.Add(funbtn, 0, wx.ALL, 10)
        panel.SetSizer(sizer)
        panel.Layout()


    def OnTimeToClose(self, evt):
        """Event handler for the button click."""
        print("See ya later!")
        self.Close()

    def OnFunButton(self, evt):
        """Event handler for the button click."""
        print("Having fun yet?")


class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, "Simple wxPython App")
        self.SetTopWindow(frame)

        print("Print statements go to this stdout window by default.")

        frame.Show(True)
        return True


if __name__ == '__main__':

    app = wx.GetApp()
    if app is None:
        app = MyApp(redirect=False, clearSigInt=False)
    else:
        frame = MyFrame(None, "Simple wxPython App")
        app.SetTopWindow(frame)
        print("Print statements go to this stdout window by default.")
        frame.Show(True)

    try:
        from IPython.lib.inputhook import enable_gui
        enable_gui('wx', app)
    except ImportError:
        app.MainLoop()
anyone? - - - for a round of direction or help??? i still get the display error no matter what
so I set the Display Environment variable to localhost:0 with no noticible effect.
Reply
#10
I suppose I am now working on an x display....so ipython will function for me:

This is generally what I will start with and try to bring back an update:

export DISPLAY=:1
Xvfb :1 -screen 0 1600x1200x16 -fbdir /var/tmp &
x11vnc -rfbport 443 -display :1 -bg -nopw -listen localhost -xkb

I hope more research will move me forward.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020